liusheng
2024-05-12 f243bb8af00a2464d16536d42150a4107f87b4ae
代码提交
已添加2个文件
已修改7个文件
967 ■■■■■ 文件已修改
ruoyi-admin/src/main/java/com/ruoyi/web/component/RabbitMqReceiver.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/IvrLibaTemplateController.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/task/PhoneTask.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/HttpUtil.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/config/RabbitMqCallPhoneConfig.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/config/RabbitMqConfig.java 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/domain/IvrTaskcallPhoneMQ.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/domain/TestVo.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/service/impl/IvrTaskSingleServiceImpl.java 412 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/component/RabbitMqReceiver.java
@@ -2,16 +2,14 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.task.PhoneTask;
import com.ruoyi.web.task.PhoneTask2;
import com.smartor.common.SendService;
import com.smartor.config.RabbitMqConfig;
import com.smartor.domain.IvrLibaTemplateVO;
import com.smartor.domain.IvrTask;
import com.smartor.domain.IvrTaskSingle;
import com.smartor.domain.IvrTaskcallMQ;
import com.smartor.config.PhoneUtils;
import com.smartor.config.RabbitMqCallPhoneConfig;
import com.smartor.domain.*;
import com.smartor.mapper.IvrTaskMapper;
import com.smartor.mapper.IvrTaskSingleMapper;
import com.smartor.service.IIvrLibaTemplateService;
@@ -19,12 +17,11 @@
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import java.io.IOException;
import java.util.List;
@@ -35,6 +32,7 @@
@Component//监听此队列
public class RabbitMqReceiver {
    private static IIvrLibaTemplateService ivrLibaTemplateService;
    private static IvrTaskSingleMapper ivrTaskcallMapper;
@@ -44,6 +42,8 @@
    private static SendService sendService;
    private static RedisCache redisCache;
    private static RabbitMqCallPhoneConfig rabbitMqCallPhoneConfig;
    // åˆ›å»ºå›ºå®šå¤§å°çš„线程池
    private static final ExecutorService executorService = Executors.newFixedThreadPool(10);
@@ -57,6 +57,11 @@
    @Autowired
    public void setSendService(SendService sendService) {
        RabbitMqReceiver.sendService = sendService;
    }
    @Autowired
    public void setRabbitMqCallPhoneConfig(RabbitMqCallPhoneConfig rabbitMqCallPhoneConfig) {
        RabbitMqReceiver.rabbitMqCallPhoneConfig = rabbitMqCallPhoneConfig;
    }
    @Autowired
@@ -74,37 +79,22 @@
        RabbitMqReceiver.redisCache = redisCache;
    }
//    @RabbitListener(queues = RabbitMqConfig.delay_queue)
//    public void consultReceiveDealy(String content, Message message, Channel channel) throws IOException {
//        log.info("----------------接收延迟队列消息--------------------");
//        //通知 MQ æ¶ˆæ¯å·²è¢«æŽ¥æ”¶,可以ACK(从队列中删除)了
//        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
//        try {
//            log.info("=============Do Something==============");
//        } catch (Exception e) {
//            log.error("============消费失败,尝试消息补发再次消费!==============");
//            log.error(e.getMessage());
//            /**
//             * basicRecover方法是进行补发操作,
//             * å…¶ä¸­çš„参数如果为true是把消息退回到queue但是有可能被其它的consumer(集群)接收到,
//             * è®¾ç½®ä¸ºfalse是只补发给当前的consumer
//             */
//            channel.basicRecover(false);
//        }
//    }
    /**
     * ç”µè¯éšè®¿
     * concurrency = "50"  å¹¶å‘数为50
     */
    @RabbitListener(queues = RabbitMqConfig.phone_queue, concurrency = "50")
    @RabbitListener(queues = "phone_queue", concurrency = "50")
    public void phoneVisit(String content, Message message, Channel channel) throws IOException {
        try {
            IvrTaskcallMQ ivrTaskcallMQ = null;
            ObjectMapper mapper = new ObjectMapper();
            try {
                ivrTaskcallMQ = mapper.readValue("{" + content + "}", IvrTaskcallMQ.class);
                if (!content.contains("{")) {
                    ivrTaskcallMQ = mapper.readValue("{" + content + "}", IvrTaskcallMQ.class);
                } else {
                    ivrTaskcallMQ = mapper.readValue(content, IvrTaskcallMQ.class);
                }
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
@@ -125,22 +115,50 @@
                    break;
                }
//                //通过多线程的方式去打电话
//                executorService.submit(new PhoneTask(ivrTaskcall1, ivrLibaTemplateVO1, redisCache, channel, message, sendService));
                new PhoneTask2().runPhone(ivrTaskcall1, ivrLibaTemplateVO1, redisCache, channel, message, sendService);
                executorService.submit(new PhoneTask(ivrTaskcall1, ivrLibaTemplateVO1, redisCache, rabbitMqCallPhoneConfig, message, sendService));
            }
            //通知 MQ æ¶ˆæ¯å·²è¢«æŽ¥æ”¶,可以ACK(从队列中删除)了   ï¼ˆè¿™ä¸ªéœ€è¦æ ¹æ®ä¸šåŠ¡å†åŽ»å¤„ç†ACK)
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            log.info("=============Do Something==============");
        } catch (Exception e) {
            log.error("============消费失败,尝试消息补发再次消费!==============");
            log.error(e.getMessage());
            /**
             * basicRecover方法是进行补发操作,
             * å…¶ä¸­çš„参数如果为true是把消息退回到queue但是有可能被其它的consumer(集群)接收到,
             * è®¾ç½®ä¸ºfalse是只补发给当前的consumer
             */
            channel.basicRecover(false);
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
        }
    }
    /**
     * æœºå™¨äººç¬¬ä¸€å¥è¯è¯­éŸ³
     * concurrency = "50"  å¹¶å‘数为50
     */
    @RabbitListener(queues = "ob_queue", concurrency = "50")
    public void obVisit(String content, Message message, Channel channel) throws IOException {
        try {
            IvrTaskcallPhoneMQ ivrTaskcallMQ = null;
            ObjectMapper mapper = new ObjectMapper();
            ivrTaskcallMQ = mapper.readValue(content, IvrTaskcallPhoneMQ.class);
            //判断患者是否已经接电话
            String str = redisCache.getCacheObject(ivrTaskcallMQ.getUuid() + "state_id");
            System.out.println("-----------------" + str);
            if (StringUtils.isNotEmpty(str) && str.equals("0")) {
                //患者已经接听了电话
                new PhoneUtils().ttsPlayback(ivrTaskcallMQ.getScript(), ivrTaskcallMQ.getUuid());
            } else if (StringUtils.isNotEmpty(str) && str.equals("-10")) {
                //这个说明,已经打了指定遍数还是没有人接,可以将消息从队列中移除了
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                return;
            } else {
                //进行队列尾部,进行下一次校验
//                channel.basicRecover(false);
                channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
                System.out.println("++++++++++++++++++++++" + str);
                return;
            }
            //通知 MQ æ¶ˆæ¯å·²è¢«æŽ¥æ”¶,可以ACK(从队列中删除)了   ï¼ˆè¿™ä¸ªéœ€è¦æ ¹æ®ä¸šåŠ¡å†åŽ»å¤„ç†ACK)
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            log.error("============消费失败,尝试消息补发再次消费!==============");
            log.error(e.getMessage());
            channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
        }
    }
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/IvrLibaTemplateController.java
@@ -1,7 +1,6 @@
package com.ruoyi.web.controller.smartor;
import com.alibaba.fastjson2.JSON;
import com.google.gson.Gson;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@@ -10,7 +9,7 @@
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.smartor.config.PhoneUtils;
import com.smartor.config.RabbitMqConfig;
import com.smartor.config.RabbitMqCallPhoneConfig;
import com.smartor.domain.IvrLibaTemplate;
import com.smartor.domain.IvrLibaTemplateVO;
import com.smartor.domain.Test1Vo;
@@ -19,19 +18,12 @@
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * éšè®¿æ¨¡æ¿åº“Controller
@@ -47,11 +39,14 @@
    @Autowired
    private IIvrLibaTemplateService ivrLibaTemplateService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
//    @Autowired
//    private RabbitTemplate rabbitTemplate;
    @Autowired
    private PhoneUtils phoneUtils;
    @Autowired
    private RabbitMqCallPhoneConfig rabbitMqCallPhoneConfig;
    /**
     * æŸ¥è¯¢æ¨¡æ¿åº“列表
@@ -152,30 +147,19 @@
    @PostMapping("/queryRabbitmq")
    public AjaxResult queryRabbitmq(@RequestBody Test1Vo test1Vo) {
//        rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_NAME, "phone.001", "测试数据001");
//        rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_NAME, "phone.002", "测试数据002");
//        rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_NAME, "phone.003", "测试数据003");
//        rabbitTemplate.convertAndSend(RabbitMqConfig.EXCHANGE_NAME, routintKey, message, new MessagePostProcessor() {
//            @Override
//            public Message postProcessMessage(Message message) throws AmqpException {
////                message.getMessageProperties().setDelay(times);
//                message.getMessageProperties().getHeaders().put("x-delay", times);
////message.getMessageProperties().setExpiration();
//                return message;
//            }
//        });
        log.info("-------------启动咨询应答超时提醒延迟队列-------------");
        String data = JSON.toJSONString(test1Vo.getTestVo());
        String substring = data.substring(1, data.length() - 1);
        rabbitMqCallPhoneConfig.sendMessage("phone_exchange", "phone.123", substring, test1Vo.getTimes());
        this.rabbitTemplate.convertAndSend(RabbitMqConfig.phone_exchange, RabbitMqConfig.routing_key, substring, message -> {
            //注意这里时间可以使long,而且是设置header
            message.getMessageProperties().setHeader("x-delay", test1Vo.getTimes());
            return message;
        });
        log.info("-------------延迟队列{}ms后执行.-------------", test1Vo.getTimes());
        return success();
    }
    @GetMapping("/tts")
    public AjaxResult tts(@RequestParam("fileText") String fileText, @RequestParam("uuid") String uuid) {
        new PhoneUtils().ttsPlayback(fileText, uuid);
        return success();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/task/PhoneTask.java
@@ -1,15 +1,16 @@
package com.ruoyi.web.task;
import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DtoConversionUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.smartor.common.SendService;
import com.smartor.config.PhoneUtils;
import com.smartor.config.RabbitMqCallPhoneConfig;
import com.smartor.domain.*;
import org.springframework.amqp.core.Message;
import org.springframework.data.convert.Jsr310Converters;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -19,79 +20,95 @@
    private List<IvrLibaTemplateScriptVO> ivrLibaTemplateScriptVO;
    private RedisCache redisCache;
    private IvrLibaTemplateVO ivrLibaTemplateVO;
    private Channel channel;
    private RabbitMqCallPhoneConfig rabbitMqCallPhoneConfig;
    private Message message;
    private SendService sendService;
    public PhoneTask(IvrTaskSingle ivrTaskSingle, IvrLibaTemplateVO ivrLibaTemplateVO, RedisCache redisCache, Channel channel, Message message, SendService sendService) {
    public PhoneTask(IvrTaskSingle ivrTaskSingle, IvrLibaTemplateVO ivrLibaTemplateVO, RedisCache redisCache, RabbitMqCallPhoneConfig rabbitMqCallPhoneConfig, Message message, SendService sendService) {
        this.ivrTaskSingle = DtoConversionUtils.sourceToTarget(ivrTaskSingle, IvrTaskSingle.class);
        this.ivrLibaTemplateScriptVO = DtoConversionUtils.sourceToTarget(ivrLibaTemplateVO.getIvrLibaTemplateScriptVOList(), IvrLibaTemplateScriptVO.class);
        this.ivrLibaTemplateVO = DtoConversionUtils.sourceToTarget(ivrLibaTemplateVO, IvrLibaTemplateVO.class);
        this.redisCache = redisCache;
        this.channel = channel;
        this.rabbitMqCallPhoneConfig = rabbitMqCallPhoneConfig;
        this.message = message;
        this.sendService = sendService;
    }
    @Override
    public void run() {
        synchronized (PhoneTask.class) {
            try {
                //获取电话组,查看哪些电话可以使用
                PhoneUtils phoneUtils = new PhoneUtils();
                final String uuid = IdUtils.randomUUID();
                //获取所有的“通配符”键值对
                ObjectMapper objectMapper = new ObjectMapper();
                Map<String, Map<String, String>> ivrTaskSingleMmap = objectMapper.readValue(ivrTaskSingle.getTextParam(), Map.class);
                List<Map<String, String>> mapList = new ArrayList<>();
                if (!Objects.isNull(ivrTaskSingleMmap)) {
                    for (Map<String, String> map : ivrTaskSingleMmap.values()) {
                        mapList.add(map);
                    }
                    //将模板问题话术里的通配符替换
                    for (IvrLibaTemplateScriptVO ivrLibaTemplateScriptVO : ivrLibaTemplateScriptVO) {
                        for (Map<String, String> map : mapList) {
                            for (String key : map.keySet()) {
                                ivrLibaTemplateScriptVO.setQuestionText(ivrLibaTemplateScriptVO.getQuestionText().replace(key, map.get(key)));
                            }
        try {
            //获取电话组,查看哪些电话可以使用
            PhoneUtils phoneUtils = new PhoneUtils();
            final String uuid = IdUtils.randomUUID();
            //获取所有的“通配符”键值对
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Map<String, String>> ivrTaskSingleMmap = objectMapper.readValue(ivrTaskSingle.getTextParam(), Map.class);
            List<Map<String, String>> mapList = new ArrayList<>();
            if (!Objects.isNull(ivrTaskSingleMmap)) {
                for (Map<String, String> map : ivrTaskSingleMmap.values()) {
                    mapList.add(map);
                }
                //将模板问题话术里的通配符替换
                for (IvrLibaTemplateScriptVO ivrLibaTemplateScriptVO : ivrLibaTemplateScriptVO) {
                    for (Map<String, String> map : mapList) {
                        for (String key : map.keySet()) {
                            ivrLibaTemplateScriptVO.setQuestionText(ivrLibaTemplateScriptVO.getQuestionText().replace(key, map.get(key)));
                        }
                    }
                }
                Map<String, Object> objectMap = new HashMap<>();
                objectMap.put("ivrTaskSingle", ivrTaskSingle);
                objectMap.put("ivrLibaTemplateScriptVO", ivrLibaTemplateScriptVO);
                //将数据放到redis中,方便在回调方法里获取
                redisCache.setCacheObject(uuid, objectMap, 120, TimeUnit.MINUTES);
                //记录首次问题
                QuestionMessage returnQues = new QuestionMessage();
                returnQues.setKcb(ivrLibaTemplateVO.getRevisitBefore());
                for (IvrLibaTemplateScriptVO ivrLibaTemplateScriptVO : ivrLibaTemplateScriptVO) {
                    if (ivrLibaTemplateScriptVO.getTargetid() == ivrLibaTemplateVO.getFirstQuestionNum().intValue()) {
                        returnQues.setNowQuestion(ivrLibaTemplateScriptVO);
                    }
                }
                returnQues.setQuestionList(ivrLibaTemplateScriptVO);
                //将问题,和模板信息放到redis中
                redisCache.setCacheObject(uuid + "returnQues", returnQues, 120, TimeUnit.MINUTES);
                redisCache.setCacheObject(uuid + "ivrLibaTemplateVO", ivrLibaTemplateVO, 120, TimeUnit.MINUTES);
                System.out.println("----------------uuID为 ï¼š" + uuid + "       " + ivrTaskSingle.getSendname() + "       " + returnQues.getNowQuestion().getQuestionText() + "     " + ivrTaskSingle.getPhone());
                //调用机器人电话,开始电话(需要将回调方法传入,这个等”电话方“告诉怎么传,现在先空着,还有第一句问题话术)
                String ob = phoneUtils.ob("", "", "", "", "", "", "", ivrTaskSingle.getPhone(), uuid, true);
                System.out.println("OB的值为:" + ob);
                //通了之后,立马去调开场白
                System.out.println("问题的值为:" + returnQues.getNowQuestion().getQuestionText() + "       " + uuid);
                phoneUtils.ttsPlayback(ivrLibaTemplateVO.getRevisitBefore() + returnQues.getNowQuestion().getQuestionText(), uuid);
//                //通知 MQ æ¶ˆæ¯å·²è¢«æŽ¥æ”¶,可以ACK(从队列中删除)了   ï¼ˆè¿™ä¸ªéœ€è¦æ ¹æ®ä¸šåŠ¡å†åŽ»å¤„ç†ACK)
//                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
            Map<String, Object> objectMap = new HashMap<>();
            objectMap.put("ivrTaskSingle", ivrTaskSingle);
            objectMap.put("ivrLibaTemplateScriptVO", ivrLibaTemplateScriptVO);
            //将数据放到redis中,方便在回调方法里获取
            redisCache.setCacheObject(uuid, objectMap, 120, TimeUnit.MINUTES);
            //记录首次问题
            QuestionMessage returnQues = new QuestionMessage();
            returnQues.setKcb(ivrLibaTemplateVO.getRevisitBefore());
            for (IvrLibaTemplateScriptVO ivrLibaTemplateScriptVO : ivrLibaTemplateScriptVO) {
                if (ivrLibaTemplateScriptVO.getTargetid() == ivrLibaTemplateVO.getFirstQuestionNum().intValue()) {
                    returnQues.setNowQuestion(ivrLibaTemplateScriptVO);
                }
            }
            returnQues.setQuestionList(ivrLibaTemplateScriptVO);
            //将问题,和模板信息放到redis中
            redisCache.setCacheObject(uuid + "returnQues", returnQues, 120, TimeUnit.MINUTES);
            redisCache.setCacheObject(uuid + "ivrLibaTemplateVO", ivrLibaTemplateVO, 120, TimeUnit.MINUTES);
            System.out.println("----------------uuID为 ï¼š" + uuid + "       " + ivrTaskSingle.getSendname() + "       " + returnQues.getNowQuestion().getQuestionText() + "     " + ivrTaskSingle.getPhone());
            //先将话术放到ob_queue队列中
            IvrTaskcallPhoneMQ ivrTaskcallPhoneMQ = new IvrTaskcallPhoneMQ();
            ivrTaskcallPhoneMQ.setScript(ivrLibaTemplateVO.getRevisitBefore() + returnQues.getNowQuestion().getQuestionText());
            ivrTaskcallPhoneMQ.setType("1");
            ivrTaskcallPhoneMQ.setUuid(uuid);
            String data = JSON.toJSONString(ivrTaskcallPhoneMQ);
            rabbitMqCallPhoneConfig.sendMessage("phone_exchange", "phone.ob1", data, 0L);
            //调用机器人电话,开始电话
            String ob = phoneUtils.ob("", "", "", "", "", "", "", ivrTaskSingle.getPhone(), uuid, true);
            System.out.println("----------------uuID为 ï¼š" + uuid + "       " + ivrTaskSingle.getSendname() + "       " + returnQues.getNowQuestion().getQuestionText() + "     " + ivrTaskSingle.getPhone() + "----------已经拨打");
            Map<String, String> obMap = objectMapper.readValue(ob, Map.class);
            Thread.sleep(1000);
            redisCache.setCacheObject(uuid + "state_id", "0", 10, TimeUnit.MINUTES);
//这里先注释,state_id,电话那边,只能返回6,不能返回0,还需要电话那边进行修改,那边修改之后,上面两行可删除,将下面的解开注释
//            if (obMap.get("state_id").equals("0")) {
//                // è¯´æ˜Žæ‰“通了
//                redisCache.setCacheObject(uuid + "state_id", "0", 10, TimeUnit.MINUTES);
//            } else {
//                while (true) {
//                    Thread.sleep(2000);
//                    redisCache.setCacheObject(uuid + "state_id", "0", 10, TimeUnit.MINUTES);
//                }
//            }
            System.out.println("OB的值为:" + ob);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/HttpUtil.java
@@ -77,9 +77,9 @@
        // è®¾å®šå‚数:客户端的总连接数
        manager.getParams().setMaxTotalConnections(400);
        // è®¾ç½®è¿žæŽ¥è¶…æ—¶æ—¶é—´,单位:毫秒
        manager.getParams().setConnectionTimeout(8000);
        manager.getParams().setConnectionTimeout(30000);
        // è®¾ç½®è¯·æ±‚读取超时时间,单位:毫秒
        manager.getParams().setSoTimeout(8000);
        manager.getParams().setSoTimeout(30000);
        // è®¾ç½®ä»Žè¿žæŽ¥æ± ä¸­èŽ·å–é“¾æŽ¥æ—¶é—´ï¼Œ å•位:毫秒
        manager.getParams().setParameter(HttpClientParams.CONNECTION_MANAGER_TIMEOUT, 8000);
        // ä½¿ç”¨è¿žæŽ¥æ± æŠ€æœ¯åˆ›å»ºHttpClient对象
smartor/src/main/java/com/smartor/config/RabbitMqCallPhoneConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
package com.smartor.config;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class RabbitMqCallPhoneConfig {
    @Autowired
    private AmqpAdmin amqpAdmin;
    @Autowired
    private AmqpTemplate rabbitTemplate;
    /**
     * åˆ›å»ºäº¤æ¢æœº
     *
     * @param exchangeName äº¤æ¢æœºåç§°
     */
    public void createExchange(String exchangeName) {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "topic");
        CustomExchange exchange = new CustomExchange(exchangeName, "x-delayed-message", true, false, args);
        amqpAdmin.declareExchange(exchange);
    }
    /**
     * åˆ›å»ºé˜Ÿåˆ—
     *
     * @param queueName é˜Ÿåˆ—名称
     */
    public void createQueue(String queueName) {
        Queue queue = new Queue(queueName, true, false, false);
        amqpAdmin.declareQueue(queue);
    }
    /**
     * äº¤æ¢æœºç»‘定
     *
     * @param changeName äº¤æ¢æœºåç§°
     * @param routingKey è·¯ç”±key
     * @param queueName  é˜Ÿåˆ—名称
     */
    public void bindExchange(String changeName, String routingKey, String queueName) {
        Binding binding = new Binding(queueName, Binding.DestinationType.QUEUE, changeName, routingKey, null);
        amqpAdmin.declareBinding(binding);
    }
    /**
     * å‘送信息到交换机
     *
     * @param changeName äº¤æ¢æœºåç§°
     * @param routingKey è·¯ç”±key
     * @param data       æ¶ˆæ¯
     */
    public void sendMessage(String changeName, String routingKey, String data, Long times) {
        this.rabbitTemplate.convertAndSend(changeName, routingKey, data, message -> {
            //注意这里时间可以使long,而且是设置header
            message.getMessageProperties().setHeader("x-delay", times);
            return message;
        });
//        rabbitTemplate.convertAndSend(changeName, routingKey, message);
    }
    /**
     * åˆ é™¤äº¤æ¢æœº
     *
     * @param changeName äº¤æ¢æœºåç§°
     */
    public void deleteExchange(String changeName) {
        amqpAdmin.deleteExchange(changeName);
    }
    /**
     * åˆ é™¤é˜Ÿåˆ—
     *
     * @param queueName é˜Ÿåˆ—名称
     */
    public void deleteQueue(String queueName) {
        amqpAdmin.deleteQueue(queueName);
    }
    /**
     * åˆ›å»ºMQ
     *
     * @param exchangName
     * @param queueName
     * @param routingKey
     * @return
     */
    public Boolean createRabbitMq(String exchangName, String queueName, String routingKey) {
        this.createExchange(exchangName);
        this.createQueue(queueName);
        this.bindExchange(exchangName, routingKey, queueName);
        return true;
    }
    /**
     * å…ˆå°†éœ€è¦åˆ›å»ºçš„队列建好
     */
    @Bean
    public void createMq() {
        createRabbitMq("phone_exchange", "ob_queue", "phone.ob1");
        createRabbitMq("phone_exchange", "phone_queue", "phone.123");
    }
}
smartor/src/main/java/com/smartor/config/RabbitMqConfig.java
@@ -1,91 +1,57 @@
package com.smartor.config;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class RabbitMqConfig {
//    public static final String EXCHANGE_NAME = "phone_topic_exchange2";
//    public static final String QUEUE_NAME = "phone_queue";
    //
//    /**
//     * topic交换机,并持久化
//     */
//    @Bean(EXCHANGE_NAME)
//    public Exchange phoneExchange() {
//        Map<String, Object> arguments = new HashMap<>();
//        //指定通信方式为topic
//        arguments.put("x-delayed-type", "topic");
//        //使用CustomExchange类创建,类型要指定为“x-delayed-message”类型
//        Exchange exchange = new CustomExchange(EXCHANGE_NAME, "x-delayed-message", true, false, arguments);
//        return exchange;
//package com.smartor.config;
//
////
////        return ExchangeBuilder.topicExchange(EXCHANGE_NAME).durable(true).build();
//    }
//import org.springframework.amqp.core.*;
//import org.springframework.beans.factory.annotation.Qualifier;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
//import java.util.HashMap;
//import java.util.Map;
//
////@Configuration
//public class RabbitMqConfig {
//
////定义延迟队列
//    public static final String phone_queue = "phone_queue";
//    //定义延迟交换机
//    public static final String phone_exchange = "phone_exchange";
//    //定义路由键
//    public static final String routing_key = "phone.123";
//
//
//    /**
//     * é˜Ÿåˆ—
//     */
//    @Bean(QUEUE_NAME)
//    public Queue phoneQueue() {
//        return QueueBuilder.durable(QUEUE_NAME).build();
//    }
//
//    /**
//     * äº¤æ¢æœºä¸Žé˜Ÿåˆ—的绑定
//     * å®šä¹‰å»¶è¿Ÿé˜Ÿåˆ—
//     *
//     * @return
//     */
//    @Bean
//    public Binding bindQueueExchange(@Qualifier(QUEUE_NAME) Queue phoneQueue, @Qualifier(EXCHANGE_NAME) Exchange phoneExchange) {
//        return BindingBuilder.bind(phoneQueue).to(phoneExchange).with(" phone.#").noargs();
//    public Queue delayQueue() {
//        return new Queue(phone_queue, true);
//    }
//定义延迟队列
    public static final String phone_queue = "phone_queue";
    //定义延迟交换机
    public static final String phone_exchange = "phone_exchange";
    //定义路由键
    public static final String routing_key = "phone.123";
    /**
     * å®šä¹‰å»¶è¿Ÿé˜Ÿåˆ—
     *
     * @return
     */
    @Bean
    public Queue delayQueue() {
        return new Queue(phone_queue, true);
    }
    /**
     * å»¶æ—¶é˜Ÿåˆ—交换机
     * äº¤æ¢æœºç±»åž‹ï¼šCustomExchange
     *
     * @return
     */
    @Bean
    public CustomExchange delayExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "topic");
        return new CustomExchange(phone_exchange, "x-delayed-message", true, false, args);
    }
    /**
     * ä¸ºå»¶è¿Ÿé˜Ÿåˆ—绑定交换机
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding delayBinding(Queue queue, CustomExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(routing_key).noargs();
    }
}
//
//    /**
//     * å»¶æ—¶é˜Ÿåˆ—交换机
//     * äº¤æ¢æœºç±»åž‹ï¼šCustomExchange
//     *
//     * @return
//     */
//    @Bean
//    public CustomExchange delayExchange() {
//        Map<String, Object> args = new HashMap<>();
//        args.put("x-delayed-type", "topic");
//        return new CustomExchange(phone_exchange, "x-delayed-message", true, false, args);
//    }
//
//    /**
//     * ä¸ºå»¶è¿Ÿé˜Ÿåˆ—绑定交换机
//     *
//     * @param queue
//     * @param exchange
//     * @return
//     */
//    @Bean
//    public Binding delayBinding(Queue queue, CustomExchange exchange) {
//        return BindingBuilder.bind(queue).to(exchange).with(routing_key).noargs();
//    }
//
//}
smartor/src/main/java/com/smartor/domain/IvrTaskcallPhoneMQ.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package com.smartor.domain;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * MQ任务
 *
 * @author ruoyi
 * @date 2024-02-02
 */
@Data
public class IvrTaskcallPhoneMQ extends BaseEntity {
    private static final long serialVersionUID = 1L;
    /**
     * ç±»åž‹: 1 ç”µè¯  2其它
     */
    @ApiModelProperty(value = "类型:  1 ç”µè¯  2其它")
    private String type;
    @ApiModelProperty(value = "问题")
    private String script;
    @ApiModelProperty(value = "问题")
    private String uuid;
}
smartor/src/main/java/com/smartor/domain/TestVo.java
@@ -28,5 +28,7 @@
    @ApiModelProperty(value = "发送类型: 1 æ—¶é—´æ®µ   2 å³åˆ»å‘送")
    private String sendType;
    private String type;
}
smartor/src/main/java/com/smartor/service/impl/IvrTaskSingleServiceImpl.java
@@ -4,15 +4,12 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DtoConversionUtils;
//import com.smartor.config.PhoneUtils;
import com.smartor.config.PhoneUtils;
import com.smartor.config.RabbitMqConfig;
import com.smartor.config.RabbitMqCallPhoneConfig;
import com.smartor.domain.*;
import com.smartor.mapper.*;
import com.smartor.service.IIvrTaskService;
@@ -21,7 +18,6 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -63,7 +59,7 @@
    private IvrLibaExtemplatescriptMapper ivrLibaExtemplatescriptMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    private RabbitMqCallPhoneConfig rabbitMqCallPhoneConfig;
    /**
@@ -280,11 +276,8 @@
            String ivrTaskcallMQJson = JSON.toJSONString(ivrTaskcallMQ);
            ivrTaskcallMQJson = ivrTaskcallMQJson.substring(1, ivrTaskcallMQJson.length() - 1);
            //立即发送
            rabbitTemplate.convertAndSend(RabbitMqConfig.phone_exchange, RabbitMqConfig.routing_key, ivrTaskcallMQJson, message -> {
                //注意这里时间可以使long,而且是设置header
                message.getMessageProperties().setHeader("x-delay", 0);
                return message;
            });
            rabbitMqCallPhoneConfig.sendMessage("phone_exchange", "phone.123", ivrTaskcallMQJson, 0L);
        } else if (ivrTaskcallVO.getSendType().equals("1")) {
            //时间段发送
            if (CollectionUtils.isNotEmpty(ivrTaskcallVO.getSendTimeslot())) {
@@ -314,11 +307,7 @@
                    Long finalMilliseconds = milliseconds;
                    String ivrTaskcallMQJson = JSON.toJSONString(ivrTaskcallMQ);
                    ivrTaskcallMQJson = ivrTaskcallMQJson.substring(1, ivrTaskcallMQJson.length() - 1);
                    rabbitTemplate.convertAndSend(RabbitMqConfig.phone_exchange, RabbitMqConfig.routing_key, ivrTaskcallMQJson, message -> {
                        //注意这里时间可以使long,而且是设置header
                        message.getMessageProperties().setHeader("x-delay", finalMilliseconds);
                        return message;
                    });
                    rabbitMqCallPhoneConfig.sendMessage("phone_exchange", "phone.123", ivrTaskcallMQJson, 0L);
                }
                //将任务状态修改成执行中
                IvrTask ivrTask = new IvrTask();
@@ -333,168 +322,127 @@
    @Override
    public void phoneCallBack(PhoneCallBackVO phoneCallBackVO) {
        synchronized (new IvrTaskSingleServiceImpl()) {
            phoneCallBackVO.setTextResult(phoneCallBackVO.getTextResult().substring(0, phoneCallBackVO.getTextResult().length() - 1));
            SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
            //获取数据
            Boolean aBoolean = redisCache.hasKey(phoneCallBackVO.getUuid());
            if (!aBoolean) {
                throw new BaseException("该uuid不存在");
            }
            Integer hangupValue = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "hangup");
            PhoneUtils phoneUtils = new PhoneUtils();
            if (hangupValue != null && hangupValue == 1) {
        phoneCallBackVO.setTextResult(phoneCallBackVO.getTextResult().substring(0, phoneCallBackVO.getTextResult().length() - 1));
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        //获取数据
        Boolean aBoolean = redisCache.hasKey(phoneCallBackVO.getUuid());
        if (!aBoolean) {
            throw new BaseException("该uuid不存在");
        }
        Integer hangupValue = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "hangup");
        PhoneUtils phoneUtils = new PhoneUtils();
        if (hangupValue != null && hangupValue == 1) {
            String date = simpleDateFormat1.format(new Date());
            log.info("电话要挂断了: {}", date);
            //hangupValue == 1  éšè®¿ç»“束,直接可以挂电话
            phoneUtils.hangup("", "", "", "", "", "", "", phoneCallBackVO.getUuid());
            return;
        }
        Map<String, Object> map = redisCache.getCacheObject(phoneCallBackVO.getUuid());
        IvrTaskSingle ivrTaskcall = (IvrTaskSingle) map.get("ivrTaskSingle");
        List<IvrLibaTemplateScriptVO> ivrLibaTemplateScriptVOs = (List<IvrLibaTemplateScriptVO>) map.get("ivrLibaTemplateScriptVO");
        //将uuid更新到数据库中
        ivrTaskcall.setSenduuid(phoneCallBackVO.getUuid());
        ivrTaskSingleMapper.updateIvrTaskcall(ivrTaskcall);
        //获取模板信息
        IvrLibaTemplateVO ivrLibaTemplateVO = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "ivrLibaTemplateVO");
        //语音识别结果上报接口: 3
        Integer noVoice = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "noVoice");
        QuestionMessage returnQues = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "returnQues");
        //将传回的结果放到回复对象中
        returnQues.setContent(phoneCallBackVO.getTextResult());
        IvrLibaTemplateScriptVO nowQuestion = returnQues.getNowQuestion();
        if (StringUtils.isEmpty(returnQues.getContent())) {
            //无回话
            //判断noVoice是否已经到了最大值
            if (noVoice == ivrLibaTemplateVO.getNoVoiceNum().intValue()) {
                //已经问了对应的遍数,就判断是否还有下一题
                if (nowQuestion.getTargetid() == ivrLibaTemplateScriptVOs.size()) {
                    //没有下一题了,就挂断电话,播放结束语
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES);
                    phoneUtils.ttsPlayback(ivrLibaTemplateVO.getRevisitAfter(), phoneCallBackVO.getUuid());
                    return;
                } else {
                    //有下一题
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "noVoice", 0, 120, TimeUnit.MINUTES);
                    IvrLibaTemplateScriptVO nextQuestion = getNextQuestion(ivrLibaTemplateScriptVOs, nowQuestion);
                    // é—®é¢˜ï¼Œ  åŽ»è°ƒç”¨â€œtts合成和播放”接口
                    String date = simpleDateFormat1.format(new Date());
                    log.info("去调用tts合成和播放接口: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                    phoneUtils.ttsPlayback(nowQuestion.getQuestionText(), phoneCallBackVO.getUuid());
                }
            } else {
                redisCache.setCacheObject(phoneCallBackVO.getUuid() + "noVoice", noVoice + 1, 120, TimeUnit.MINUTES);
                //调用ivrLibaTemplateScriptVO中的slienceText(静默话术)
                String slienceText = nowQuestion.getSlienceText();
                //静默话术  + é—®é¢˜ï¼Œ  åŽ»è°ƒç”¨â€œtts合成和播放”接口
                String date = simpleDateFormat1.format(new Date());
                log.info("电话要挂断了: {}", date);
                //hangupValue == 1  éšè®¿ç»“束,直接可以挂电话
                phoneUtils.hangup("", "", "", "", "", "", "", phoneCallBackVO.getUuid());
                log.info("静默话术  + é—®é¢˜,去调用tts合成和播放接口: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                phoneUtils.ttsPlayback(slienceText + nowQuestion.getQuestionText(), phoneCallBackVO.getUuid());
                return;
            }
            Map<String, Object> map = redisCache.getCacheObject(phoneCallBackVO.getUuid());
            IvrTaskSingle ivrTaskcall = (IvrTaskSingle) map.get("ivrTaskSingle");
            List<IvrLibaTemplateScriptVO> ivrLibaTemplateScriptVOs = (List<IvrLibaTemplateScriptVO>) map.get("ivrLibaTemplateScriptVO");
            //将uuid更新到数据库中
            ivrTaskcall.setSenduuid(phoneCallBackVO.getUuid());
            ivrTaskSingleMapper.updateIvrTaskcall(ivrTaskcall);
            //获取模板信息
            IvrLibaTemplateVO ivrLibaTemplateVO = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "ivrLibaTemplateVO");
            //语音识别结果上报接口: 3
            Integer noVoice = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "noVoice");
            QuestionMessage returnQues = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "returnQues");
            //将传回的结果放到回复对象中
            returnQues.setContent(phoneCallBackVO.getTextResult());
            IvrLibaTemplateScriptVO nowQuestion = returnQues.getNowQuestion();
            if (StringUtils.isEmpty(returnQues.getContent())) {
                //无回话
                //判断noVoice是否已经到了最大值
                if (noVoice == ivrLibaTemplateVO.getNoVoiceNum().intValue()) {
                    //已经问了对应的遍数,就判断是否还有下一题
                    if (nowQuestion.getTargetid() == ivrLibaTemplateScriptVOs.size()) {
                        //没有下一题了,就挂断电话,播放结束语
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES);
                        phoneUtils.ttsPlayback(ivrLibaTemplateVO.getRevisitAfter(), phoneCallBackVO.getUuid());
                        return;
                    } else {
                        //有下一题
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "noVoice", 0, 120, TimeUnit.MINUTES);
                        IvrLibaTemplateScriptVO nextQuestion = getNextQuestion(ivrLibaTemplateScriptVOs, nowQuestion);
                        // é—®é¢˜ï¼Œ  åŽ»è°ƒç”¨â€œtts合成和播放”接口
                        String date = simpleDateFormat1.format(new Date());
                        log.info("去调用tts合成和播放接口: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                        phoneUtils.ttsPlayback(nowQuestion.getQuestionText(), phoneCallBackVO.getUuid());
                    }
                } else {
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "noVoice", noVoice + 1, 120, TimeUnit.MINUTES);
                    //调用ivrLibaTemplateScriptVO中的slienceText(静默话术)
                    String slienceText = nowQuestion.getSlienceText();
                    //静默话术  + é—®é¢˜ï¼Œ  åŽ»è°ƒç”¨â€œtts合成和播放”接口
                    String date = simpleDateFormat1.format(new Date());
                    log.info("静默话术  + é—®é¢˜,去调用tts合成和播放接口: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                    phoneUtils.ttsPlayback(slienceText + nowQuestion.getQuestionText(), phoneCallBackVO.getUuid());
                    return;
        } else {
            //isppd用来记录是否匹配到
            Boolean isppd = false;
            //有回话,对回答的问题,进行正则匹配(这里只针对选择题,其它题型不行)
            for (int j = 0; j < nowQuestion.getIvrLibaScriptTargetoptionList().size(); j++) {
                //包含
                Matcher matcher = null;
                if (StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex())) {
                    Pattern pattern = Pattern.compile(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex());
                    matcher = pattern.matcher(phoneCallBackVO.getTextResult());
                }
            } else {
                //isppd用来记录是否匹配到
                Boolean isppd = false;
                //有回话,对回答的问题,进行正则匹配(这里只针对选择题,其它题型不行)
                for (int j = 0; j < nowQuestion.getIvrLibaScriptTargetoptionList().size(); j++) {
                    //包含
                    Matcher matcher = null;
                    if (StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex())) {
                        Pattern pattern = Pattern.compile(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex());
                        matcher = pattern.matcher(phoneCallBackVO.getTextResult());
                    }
                    //不包含
                    Matcher matcher2 = null;
                    if (StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex2())) {
                        Pattern pattern2 = Pattern.compile(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex2());
                        matcher2 = pattern2.matcher(phoneCallBackVO.getTextResult());
                    }
                    log.error("PCB--getQuestionText问题为:{},UUID:{}", nowQuestion.getQuestionText(), phoneCallBackVO.getUuid());
                    if (StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex2()) && matcher2.matches() && StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex()) && matcher.matches() || StringUtils.isEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex()) && StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex2()) && matcher2.matches() || StringUtils.isEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex2()) && StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex()) && matcher.matches()) {
                        //说明匹配正确了
                        //这里应该先判断类型,去再修改,设置IsUserOperation是单选题的改法
                        nowQuestion.getIvrLibaScriptTargetoptionList().get(j).setIsUserOperation(true);
                        ivrLibaScriptTargetoptionMapper.updateIvrLibaTemplateTargetoption(nowQuestion.getIvrLibaScriptTargetoptionList().get(j));
                        //将静默置为0
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "noVoice", 0, 120, TimeUnit.MINUTES);
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "mateNum", 0, 120, TimeUnit.MINUTES);
                        //将患者的回签写进表里
                        IvrTaskVisitResult ivrTaskVisitResult = DtoConversionUtils.sourceToTarget(ivrTaskcall, IvrTaskVisitResult.class);
                        ivrTaskVisitResult.setId(null);
                        ivrTaskVisitResult.setQuestion(nowQuestion.getQuestionText());
                        ivrTaskVisitResult.setPatientAnswer(phoneCallBackVO.getTextResult());
                        ivrTaskVisitResult.setCreateTime(new Date());
                        ivrTaskVisitResult.setOptionResult(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetvalue());
                        ivrTaskVisitResultMapper.insertIvrTaskVisitResult(ivrTaskVisitResult);
                        //将匹配到的标识改成true
                        isppd = true;
                        //获取下一题
                        Integer nextQuestion = nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getNextQuestion();
                        for (IvrLibaTemplateScriptVO script : ivrLibaTemplateScriptVOs) {
                            if (script.getTargetid() == nextQuestion) {
                                QuestionMessage questionMessage = new QuestionMessage();
                                questionMessage.setNowQuestion(script);
                                questionMessage.setQuestionList(ivrLibaTemplateScriptVOs);
                                redisCache.setCacheObject(phoneCallBackVO.getUuid() + "returnQues", questionMessage, 120, TimeUnit.MINUTES);
                                phoneUtils.ttsPlayback(script.getQuestionText(), phoneCallBackVO.getUuid());
                                return;
                            } else if (nextQuestion > ivrLibaTemplateScriptVOs.size()) {
                                //没有下一题了,就结束了
                                String date = simpleDateFormat1.format(new Date());
                                log.error("没有下一题了,就结束了: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                                redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES);
                                phoneUtils.ttsPlayback(ivrLibaTemplateVO.getRevisitAfter(), phoneCallBackVO.getUuid());
                                try {
                                    Thread.sleep(3000);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                phoneUtils.hangup("", "", ivrLibaTemplateVO.getRevisitAfter(), "", "", "", "", phoneCallBackVO.getUuid());
                                return;
                            }
                        }
                        return;
                    } else {
                        //没有匹配上当前option
                        //Targetregex2 ä¸ºfalse,表示在Targetregex2中存在  è¯­å¥ä¸­çš„关键字,这个option就不用再继续匹配了,直接匹配下一个option
                        continue;
                    }
                //不包含
                Matcher matcher2 = null;
                if (StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex2())) {
                    Pattern pattern2 = Pattern.compile(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex2());
                    matcher2 = pattern2.matcher(phoneCallBackVO.getTextResult());
                }
                log.error("PCB--getQuestionText问题为:{},UUID:{}", nowQuestion.getQuestionText(), phoneCallBackVO.getUuid());
                if (StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex2()) && matcher2.matches() && StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex()) && matcher.matches() || StringUtils.isEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex()) && StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex2()) && matcher2.matches() || StringUtils.isEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex2()) && StringUtils.isNotEmpty(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetregex()) && matcher.matches()) {
                    //说明匹配正确了
                    //这里应该先判断类型,去再修改,设置IsUserOperation是单选题的改法
                    nowQuestion.getIvrLibaScriptTargetoptionList().get(j).setIsUserOperation(true);
                    ivrLibaScriptTargetoptionMapper.updateIvrLibaTemplateTargetoption(nowQuestion.getIvrLibaScriptTargetoptionList().get(j));
                if (isppd != true) {
                    //没有匹配到
                    Integer mateNum = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "mateNum");
                    if (mateNum == null) mateNum = 0;
                    //无匹配次数去判断是否到最大询问次数,并且所有的选项都匹配完了
                    if (mateNum == ivrLibaTemplateVO.getMateNum().intValue()) {
                        //如果下一题为空.则新的数据返回,并加上感谢语
                        if (nowQuestion.getTargetid() < ivrLibaTemplateScriptVOs.size()) {
                    //将静默置为0
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "noVoice", 0, 120, TimeUnit.MINUTES);
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "mateNum", 0, 120, TimeUnit.MINUTES);
                    //将患者的回签写进表里
                    IvrTaskVisitResult ivrTaskVisitResult = DtoConversionUtils.sourceToTarget(ivrTaskcall, IvrTaskVisitResult.class);
                    ivrTaskVisitResult.setId(null);
                    ivrTaskVisitResult.setQuestion(nowQuestion.getQuestionText());
                    ivrTaskVisitResult.setPatientAnswer(phoneCallBackVO.getTextResult());
                    ivrTaskVisitResult.setCreateTime(new Date());
                    ivrTaskVisitResult.setOptionResult(nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getTargetvalue());
                    ivrTaskVisitResultMapper.insertIvrTaskVisitResult(ivrTaskVisitResult);
                    //将匹配到的标识改成true
                    isppd = true;
                    //获取下一题
                    Integer nextQuestion = nowQuestion.getIvrLibaScriptTargetoptionList().get(j).getNextQuestion();
                    for (IvrLibaTemplateScriptVO script : ivrLibaTemplateScriptVOs) {
                        if (script.getTargetid() == nextQuestion) {
                            QuestionMessage questionMessage = new QuestionMessage();
                            IvrLibaTemplateScriptVO nextQuestion = getNextQuestion(ivrLibaTemplateScriptVOs, nowQuestion);
                            questionMessage.setNowQuestion(script);
                            questionMessage.setQuestionList(ivrLibaTemplateScriptVOs);
                            questionMessage.setNowQuestion(nextQuestion);
                            redisCache.setCacheObject(phoneCallBackVO.getUuid() + "returnQues", questionMessage, 120, TimeUnit.MINUTES);
                            redisCache.setCacheObject(phoneCallBackVO.getUuid() + "mateNum", 0, 120, TimeUnit.MINUTES);
                            String date = simpleDateFormat1.format(new Date());
                            log.info("如果下一题为空.则新的数据返回,并加上感谢语: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                            phoneUtils.ttsPlayback(nextQuestion.getQuestionText(), phoneCallBackVO.getUuid());
                            phoneUtils.ttsPlayback(script.getQuestionText(), phoneCallBackVO.getUuid());
                            return;
                        } else {
                            //就可以挂断电话了
                        } else if (nextQuestion > ivrLibaTemplateScriptVOs.size()) {
                            //没有下一题了,就结束了
                            String date = simpleDateFormat1.format(new Date());
                            log.info("就可以挂断电话了------: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                            log.error("没有下一题了,就结束了: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                            redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES);
                            phoneUtils.ttsPlayback(ivrLibaTemplateVO.getRevisitAfter(), phoneCallBackVO.getUuid());
                            try {
@@ -505,62 +453,102 @@
                            phoneUtils.hangup("", "", ivrLibaTemplateVO.getRevisitAfter(), "", "", "", "", phoneCallBackVO.getUuid());
                            return;
                        }
                    } else if (mateNum < ivrLibaTemplateVO.getMateNum().intValue()) {
                        //没有问到规定次数
                        mateNum = mateNum + 1;
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "mateNum", mateNum, 120, TimeUnit.MINUTES);
                    }
                    return;
                } else {
                    //没有匹配上当前option
                    //Targetregex2 ä¸ºfalse,表示在Targetregex2中存在  è¯­å¥ä¸­çš„关键字,这个option就不用再继续匹配了,直接匹配下一个option
                    continue;
                }
                //选项匹配完成后,需要再去通过库再进行匹配一次
                String extemplateID = ivrLibaTemplateVO.getSubmoduleID();
                String[] split = extemplateID.split(",");
                List<String> list = Arrays.asList(split);
                List<Long> list1 = new ArrayList<>();
                if (StringUtils.isNotEmpty(extemplateID)) {
                    for (String str : list) {
                        list1.add(Long.valueOf(str));
                    }
                    List<IvrLibaExtemplatescript> ivrLibaExtemplatescripts = ivrLibaExtemplatescriptMapper.queryIvrLibaExtemplatescriptList(list1);
                    for (IvrLibaExtemplatescript ivrLibaExtemplatescript : ivrLibaExtemplatescripts) {
                        Matcher matcher = null;
                        if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex())) {
                            Pattern pattern = Pattern.compile(ivrLibaExtemplatescript.getSelfRegex());
                            matcher = pattern.matcher(returnQues.getContent());
                        }
            }
                        Matcher matcher2 = null;
                        if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2())) {
                            Pattern pattern2 = Pattern.compile(ivrLibaExtemplatescript.getSelfRegex2());
                            matcher2 = pattern2.matcher(returnQues.getContent());
            if (isppd != true) {
                //没有匹配到
                Integer mateNum = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "mateNum");
                if (mateNum == null) mateNum = 0;
                //无匹配次数去判断是否到最大询问次数,并且所有的选项都匹配完了
                if (mateNum == ivrLibaTemplateVO.getMateNum().intValue()) {
                    //如果下一题为空.则新的数据返回,并加上感谢语
                    if (nowQuestion.getTargetid() < ivrLibaTemplateScriptVOs.size()) {
                        QuestionMessage questionMessage = new QuestionMessage();
                        IvrLibaTemplateScriptVO nextQuestion = getNextQuestion(ivrLibaTemplateScriptVOs, nowQuestion);
                        questionMessage.setQuestionList(ivrLibaTemplateScriptVOs);
                        questionMessage.setNowQuestion(nextQuestion);
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "returnQues", questionMessage, 120, TimeUnit.MINUTES);
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "mateNum", 0, 120, TimeUnit.MINUTES);
                        String date = simpleDateFormat1.format(new Date());
                        log.info("如果下一题为空.则新的数据返回,并加上感谢语: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                        phoneUtils.ttsPlayback(nextQuestion.getQuestionText(), phoneCallBackVO.getUuid());
                        return;
                    } else {
                        //就可以挂断电话了
                        String date = simpleDateFormat1.format(new Date());
                        log.info("就可以挂断电话了------: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES);
                        phoneUtils.ttsPlayback(ivrLibaTemplateVO.getRevisitAfter(), phoneCallBackVO.getUuid());
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        log.info("++++++++++++++++++++++++++通用库是否为空:selfRegex : {} , selfRegex2 : {}", ivrLibaExtemplatescript.getSelfRegex(), ivrLibaExtemplatescript.getSelfRegex2());
                        if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex()) && matcher.matches() && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && matcher2.matches() || StringUtils.isEmpty(ivrLibaExtemplatescript.getSelfRegex()) && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && matcher2.matches() || StringUtils.isEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex()) && matcher.matches()) {
                            QuestionMessage questionMessage = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "returnQues");
                            IvrLibaTemplateScriptVO ivrLibaTemplateScriptVO = returnQues.getNowQuestion();
                            ivrLibaTemplateScriptVO.setSubmoduleText(ivrLibaExtemplatescript.getSwitchText());
                            ivrLibaTemplateScriptVO.setSubmoduleVoice(ivrLibaExtemplatescript.getSwitchWav());
                        phoneUtils.hangup("", "", ivrLibaTemplateVO.getRevisitAfter(), "", "", "", "", phoneCallBackVO.getUuid());
                        return;
                    }
                } else if (mateNum < ivrLibaTemplateVO.getMateNum().intValue()) {
                    //没有问到规定次数
                    mateNum = mateNum + 1;
                    redisCache.setCacheObject(phoneCallBackVO.getUuid() + "mateNum", mateNum, 120, TimeUnit.MINUTES);
                }
            }
            //选项匹配完成后,需要再去通过库再进行匹配一次
            String extemplateID = ivrLibaTemplateVO.getSubmoduleID();
            String[] split = extemplateID.split(",");
            List<String> list = Arrays.asList(split);
            List<Long> list1 = new ArrayList<>();
            if (StringUtils.isNotEmpty(extemplateID)) {
                for (String str : list) {
                    list1.add(Long.valueOf(str));
                }
                List<IvrLibaExtemplatescript> ivrLibaExtemplatescripts = ivrLibaExtemplatescriptMapper.queryIvrLibaExtemplatescriptList(list1);
                for (IvrLibaExtemplatescript ivrLibaExtemplatescript : ivrLibaExtemplatescripts) {
                    Matcher matcher = null;
                    if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex())) {
                        Pattern pattern = Pattern.compile(ivrLibaExtemplatescript.getSelfRegex());
                        matcher = pattern.matcher(returnQues.getContent());
                    }
                    Matcher matcher2 = null;
                    if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2())) {
                        Pattern pattern2 = Pattern.compile(ivrLibaExtemplatescript.getSelfRegex2());
                        matcher2 = pattern2.matcher(returnQues.getContent());
                    }
                    log.info("++++++++++++++++++++++++++通用库是否为空:selfRegex : {} , selfRegex2 : {}", ivrLibaExtemplatescript.getSelfRegex(), ivrLibaExtemplatescript.getSelfRegex2());
                    if (StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex()) && matcher.matches() && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && matcher2.matches() || StringUtils.isEmpty(ivrLibaExtemplatescript.getSelfRegex()) && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && matcher2.matches() || StringUtils.isEmpty(ivrLibaExtemplatescript.getSelfRegex2()) && StringUtils.isNotEmpty(ivrLibaExtemplatescript.getSelfRegex()) && matcher.matches()) {
                        QuestionMessage questionMessage = redisCache.getCacheObject(phoneCallBackVO.getUuid() + "returnQues");
                        IvrLibaTemplateScriptVO ivrLibaTemplateScriptVO = returnQues.getNowQuestion();
                        ivrLibaTemplateScriptVO.setSubmoduleText(ivrLibaExtemplatescript.getSwitchText());
                        ivrLibaTemplateScriptVO.setSubmoduleVoice(ivrLibaExtemplatescript.getSwitchWav());
                        redisCache.setCacheObject(phoneCallBackVO.getUuid() + "returnQues", questionMessage, 120, TimeUnit.MINUTES);
                        if (ivrLibaExtemplatescript.getIsEnd() == 1) {
                            //将问题置空
                            IvrLibaTemplateScriptVO nowQuestion1 = questionMessage.getNowQuestion();
                            nowQuestion1.setQuestionText(null);
                            nowQuestion1.setQuestionVoice(null);
                            questionMessage.setNowQuestion(nowQuestion1);
                            redisCache.setCacheObject(phoneCallBackVO.getUuid() + "returnQues", questionMessage, 120, TimeUnit.MINUTES);
                            if (ivrLibaExtemplatescript.getIsEnd() == 1) {
                                //将问题置空
                                IvrLibaTemplateScriptVO nowQuestion1 = questionMessage.getNowQuestion();
                                nowQuestion1.setQuestionText(null);
                                nowQuestion1.setQuestionVoice(null);
                                questionMessage.setNowQuestion(nowQuestion1);
                                redisCache.setCacheObject(phoneCallBackVO.getUuid() + "returnQues", questionMessage, 120, TimeUnit.MINUTES);
                                redisCache.setCacheObject(phoneCallBackVO.getUuid() + "isOver", 1, 120, TimeUnit.MINUTES);
                            }
                            //调用“15、tts合成和播放, tts_playback”将结果传回
                            String date = simpleDateFormat1.format(new Date());
                            log.info("调用“15、tts合成和播放------: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                            phoneUtils.ttsPlayback(nowQuestion.getQuestionText() + ivrLibaTemplateScriptVO.getSubmoduleText(), phoneCallBackVO.getUuid());
                            redisCache.setCacheObject(phoneCallBackVO.getUuid() + "isOver", 1, 120, TimeUnit.MINUTES);
                        }
                        break;
                        //调用“15、tts合成和播放, tts_playback”将结果传回
                        String date = simpleDateFormat1.format(new Date());
                        log.info("调用“15、tts合成和播放------: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                        phoneUtils.ttsPlayback(nowQuestion.getQuestionText() + ivrLibaTemplateScriptVO.getSubmoduleText(), phoneCallBackVO.getUuid());
                    }
                    String date = simpleDateFormat1.format(new Date());
                    log.info("最后的信息回复-: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                    phoneUtils.ttsPlayback(nowQuestion.getQuestionText(), phoneCallBackVO.getUuid());
                    break;
                }
                String date = simpleDateFormat1.format(new Date());
                log.info("最后的信息回复-: {},uuid为:{}", date, phoneCallBackVO.getUuid());
                phoneUtils.ttsPlayback(nowQuestion.getQuestionText(), phoneCallBackVO.getUuid());
            }
        }
    }