陈昶聿
3 天以前 57eac5a31c6823962b8e77ec8a9604e41882fb32
smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskServiceImpl.java
@@ -18,7 +18,9 @@
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService;
import com.smartor.common.FtpService;
import com.smartor.common.MtSubmitSmUtil;
import com.smartor.common.ScheduleSubtaskBuilder;
@@ -137,6 +139,9 @@
    private IPatArchiveService patArchiveService;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private ScheduleSubtaskBuilder scheduleSubtaskBuilder;
    @Autowired
@@ -216,8 +221,14 @@
    private ServiceOutPathMapper serviceOutPathMapper;
    private static final String KEY_SEP = "\u0001";
    /** 二次随访生成锁前缀,防止同一原任务并发生成多条二次随访 */
    private static final String AGAIN_LOCK_KEY_PREFIX = "smartor:again:lock:";
    private static final long AGAIN_LOCK_SECONDS = 30L;
    @Autowired
    private PatMedOperationItemMapper patMedOperationItemMapper;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    /**
     * 查询单一任务(随访)
@@ -558,11 +569,22 @@
    @Override
    public List<ServiceSubtask> patItem2(ServiceSubtaskEntity serviceSubtaskEntity) {
        if (serviceSubtaskEntity.getSendstateView() != null) {
            //            1:待随访(1 被领取、2 待发送、3 已发送、5 发送失败、7、超时);2:已完成( 6 已完成)、3:无需随访(4 不执行)
            if (serviceSubtaskEntity.getSendstateView() == 1)
                serviceSubtaskEntity.setSendstates(new ArrayList<>(Arrays.asList(1L, 2L, 3L, 5L, 7L)));
            if (serviceSubtaskEntity.getSendstateView() == 2)
                serviceSubtaskEntity.setSendstates(new ArrayList<>(Arrays.asList(6L)));
            if (serviceSubtaskEntity.getSendstateView() == 3)
                serviceSubtaskEntity.setSendstates(new ArrayList<>(Arrays.asList(4L)));
        }
        List<ServiceSubtask> serviceSubtaskList = new ArrayList<>();
        for (Long sendstate : serviceSubtaskEntity.getSendstates()) {
            serviceSubtaskEntity.setSendstate(sendstate);
            List<ServiceSubtask> serviceSubtasks = serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtaskEntity);
            serviceSubtaskList.addAll(serviceSubtasks);
        if(CollectionUtils.isNotEmpty(serviceSubtaskEntity.getSendstates())){
            for (Long sendstate : serviceSubtaskEntity.getSendstates()) {
                serviceSubtaskEntity.setSendstate(sendstate);
                List<ServiceSubtask> serviceSubtasks = serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtaskEntity);
                serviceSubtaskList.addAll(serviceSubtasks);
            }
        }
        return serviceSubtaskList;
    }
@@ -633,6 +655,7 @@
            result.putIfAbsent("xsf", 0);
            result.putIfAbsent("dsf", 0);
            result.putIfAbsent("ywc", 0);
            result.putIfAbsent("cs", 0);
            result.putIfAbsent("yc", 0);
            result.putIfAbsent("jg", 0);
        }
@@ -669,6 +692,7 @@
            result.putIfAbsent("dsf", 0);
            result.putIfAbsent("dfs", 0);
            result.putIfAbsent("yfs", 0);
            result.putIfAbsent("cs", 0);
            result.putIfAbsent("ywc", 0);
            result.putIfAbsent("yc", 0);
            result.putIfAbsent("jg", 0);
@@ -769,6 +793,7 @@
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addSubTaskAgain(ServiceSubtask serviceSubtask) {
        ServiceSubtask serviceSubtask1 = selectServiceSubtaskById(serviceSubtask.getId());
        PatMedInhosp patMedInhosp = new PatMedInhosp();
@@ -778,7 +803,7 @@
        PatArchive patArchive = patArchiveMapper.selectPatArchiveByPatid(serviceSubtask1.getPatid());
        //景宁 新增再次随访不能触发患者再入院
        boolean inhospAgain = true;
        if (serviceSubtask1.getOrgid().equals("47255004333112711A1001")) {
        if ("47255004333112711A1001".equals(serviceSubtask1.getOrgid())) {
            inhospAgain = false;
        }
        if (patMedInhospList.size() > 0 && inhospAgain) {
@@ -792,13 +817,17 @@
            serviceSubtask1.setRemark(StringUtils.isNotEmpty(serviceSubtask.getRemark()) ? serviceSubtask.getRemark() + ";无需再次随访,任务被标记不在执行" : "无需再次随访,任务被标记不在执行");
            serviceSubtaskMapper.updateServiceSubtask(serviceSubtask1);
            return "无需再次随访,任务被标记不在执行";
        } else if (StringUtils.isNotEmpty(patArchive.getNotrequiredFlag()) && patArchive.getNotrequiredFlag().equals("1")) {
        } else if (patArchive != null && StringUtils.isNotEmpty(patArchive.getNotrequiredFlag()) && patArchive.getNotrequiredFlag().equals("1")) {
            serviceSubtask1.setIsVisitAgain(2);
            serviceSubtaskMapper.updateServiceSubtask(serviceSubtask1);
            serviceSubtask1.setRemark(StringUtils.isNotEmpty(serviceSubtask.getRemark()) ? serviceSubtask.getRemark() + ";无需再次随访,患者被标记不需要被服务" : "无需再次随访,患者被标记不需要被服务");
            return "无需再次随访,患者被标记不需要被服务";
        } else if (ObjectUtils.isNotEmpty(serviceSubtask1.getIsVisitAgain()) && serviceSubtask1.getIsVisitAgain() == 2) {
            return "无需再次随访,该任务已经再次随访过了";
        }
        //丽水中医院根据下次任务ID生成再次随访
        if ("47231022633110211A2101".equals(serviceSubtask1.getOrgid())) {
            return addSubTaskAgainNextTaskId(serviceSubtask1);
        }
        //新增再次随访任务
        ServiceSubtask serviceSubtask2 = DtoConversionUtils.sourceToTarget(serviceSubtask, ServiceSubtask.class);
@@ -819,6 +848,155 @@
            return "再次随访任务创建成功";
        }
        return "再次随访任务创建失败,再请次重试";
    }
    public String addSubTaskAgainNextTaskId(ServiceSubtask serviceSubtask) {
        if (ObjectUtils.isEmpty(serviceSubtask.getTaskid())) {
            log.error("再次随访任务创建失败,缺少TaskId, 再请次重试");
            return "再次随访任务创建失败,缺少TaskId, 再请次重试";
        }
        // 同一原任务串行生成,防止并发重复插入
        String lockToken = tryLockAgainTask(serviceSubtask.getId());
        if (lockToken == null) {
            return "再次随访任务正在创建中,请勿重复提交";
        }
        try {
            ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
            if (ObjectUtils.isEmpty(serviceTask)) {
                log.error("再次随访任务创建失败,找不到对应任务 taskid = {}, 再请次重试", serviceSubtask.getTaskid());
                return "再次随访任务创建失败,找不到对应任务 taskid = " + serviceSubtask.getTaskid() + ", 再请次重试";
            }
            // 幂等校验:同一原任务只允许生成一条二次随访
            ServiceSubtaskEntity againQuery = new ServiceSubtaskEntity();
            againQuery.setUpid(serviceSubtask.getId().intValue());
            if (CollectionUtils.isNotEmpty(serviceSubtaskMapper.selectServiceSubtaskList(againQuery))) {
                return "无需再次随访,该任务已经再次随访过了";
            }
            // 查询出院记录
            PatMedInhosp patMedInhospVo = new PatMedInhosp();
            patMedInhospVo.setOrgid(serviceSubtask.getOrgid());
            patMedInhospVo.setInhospid(serviceSubtask.getInhospid());
            patMedInhospVo.setCry(1);
            List<PatMedInhosp> patMedInhospList = patMedInhospService.selectPatMedInhospList(patMedInhospVo);
            PatMedInhosp patMedInhosp = new PatMedInhosp();
            if (CollectionUtils.isNotEmpty(patMedInhospList)) {
                patMedInhosp = patMedInhospList.get(0);
            } else {
                log.error("再次随访任务创建失败,任务缺少 对应的出院记录, taskid = {}, 再请次重试", serviceSubtask.getTaskid());
                return "再次随访任务创建失败,任务缺少 对应的出院记录, taskid = " + serviceSubtask.getTaskid() + ", 再请次重试";
            }
            if (ObjectUtils.isEmpty(serviceTask.getNexttaskid())) {
                log.error("再次随访任务创建失败,任务缺少 nexttaskid, taskid = {}, 再请次重试", serviceSubtask.getTaskid());
                return "再次随访任务创建失败,任务缺少 nexttaskid, taskid = " + serviceSubtask.getTaskid() + ", 再请次重试";
            }
            ServiceTask nextServiceTask = serviceTaskService.selectServiceTaskByTaskid(serviceTask.getNexttaskid());
            if (ObjectUtils.isEmpty(nextServiceTask)) {
                log.error("再次随访任务创建失败,找不到对应任务 nexttaskid = {}, 再请次重试", serviceTask.getNexttaskid());
                return "再次随访任务创建失败,找不到对应任务 nexttaskid = " + serviceTask.getNexttaskid() + ", 再请次重试";
            }
            PatArchive patArchive = patArchiveService.selectPatArchiveByPatid(serviceSubtask.getPatid());
            if (ObjectUtils.isEmpty(patArchive)) {
                log.error("再次随访任务创建失败,未找到患者档案 patid = {}, subTaskId = {}", serviceSubtask.getPatid(), serviceSubtask.getId());
                return "再次随访任务创建失败,未找到患者档案, subTaskId = " + serviceSubtask.getId() + ", 再请次重试";
            }
            String config = configService.selectConfigByKey("visit.early.day");
            Integer type = 1;
            // 随访中心科室
            String centerDept = configService.selectConfigByKey("sys.smartor.center.dept", serviceSubtask.getOrgid());
            if (ObjectUtils.isEmpty(centerDept)) {
                log.error("再次随访任务创建失败,未配置随访中心科室参数 sys.smartor.center.dept ,subTaskId = {}, 再请次重试", serviceSubtask.getId());
                return "再次随访任务创建失败,未配置随访中心科室参数 sys.smartor.center.dept ,subTaskId = " + serviceSubtask.getId() + ", 再请次重试";
            }
            SysDept sysDeptVo = new SysDept();
            sysDeptVo.setDeptType("1");
            sysDeptVo.setOrgid(serviceSubtask.getOrgid());
            sysDeptVo.setDeptCode(centerDept);
            List<SysDept> sysDepts = sysDeptService.selectDeptList(sysDeptVo);
            SysDept sysDept = new SysDept();
            if (CollectionUtils.isNotEmpty(sysDepts)) {
                sysDept = sysDepts.get(0);
            } else {
                log.error("再次随访任务创建失败,未找到参数 sys.smartor.center.dept 配置的随访中心科室 deptCode = {}, 再请次重试", centerDept);
                return "再次随访任务创建失败,未找到参数 sys.smartor.center.dept 配置的随访中心科室 deptCode = " + centerDept + ", 再请次重试";
            }
            // 按下一任务生成二次随访子任务(表单、发送方式取自下一任务)
            ServiceSubtask serviceSubtaskAgain = patMedInhospService.boxedServiceSubtask(nextServiceTask,
                    patMedInhosp, patArchive, config, type);
            if (ObjectUtils.isEmpty(serviceSubtaskAgain) || ObjectUtils.isEmpty(serviceSubtaskAgain.getTaskid())) {
                log.error("再次随访任务创建失败,下一任务生成子任务为空, subTaskId = {}, nextTaskId = {}", serviceSubtask.getId(), serviceTask.getNexttaskid());
                return "再次随访任务创建失败,患者出院记录不完整或下一任务配置异常, 再请次重试";
            }
            Date now = new Date();
            serviceSubtaskAgain.setId(null);
            serviceSubtaskAgain.setUpid(serviceSubtask.getId().intValue());
            serviceSubtaskAgain.setVisitCount(ObjectUtils.isNotEmpty(serviceSubtask.getVisitCount())
                    ? serviceSubtask.getVisitCount() + 1 : 1);
            serviceSubtaskAgain.setSendstate(2L);
            serviceSubtaskAgain.setIsVisitAgain(1);
            serviceSubtaskAgain.setCreateTime(now);
            serviceSubtaskAgain.setUpdateTime(now);
//            // 二次随访时间:上次随访完成时间(未完成则当前时间)+ 下一任务发送天数;过去时间兜底为当前时间
//            Date baseTime = ObjectUtils.isNotEmpty(serviceSubtask.getFinishtime()) ? serviceSubtask.getFinishtime() : now;
//            int intervalDays = ObjectUtils.isNotEmpty(nextServiceTask.getSendDay())
//                    ? nextServiceTask.getSendDay().intValue() : 0;
//            Date nextVisitTime = DateUtils.addDays(baseTime, intervalDays);
//            if (nextVisitTime.before(now)) {
//                nextVisitTime = now;
//            }
//            serviceSubtaskAgain.setVisitTime(nextVisitTime);
//            serviceSubtaskAgain.setLongSendTime(nextVisitTime);
            serviceSubtaskAgain.setVisitType(serviceSubtask.getVisitType());
            serviceSubtaskAgain.setVisitDeptCode(sysDept.getDeptCode());
            serviceSubtaskAgain.setVisitDeptName(sysDept.getDeptName());
            int i = serviceSubtaskMapper.insertServiceSubtask(serviceSubtaskAgain);
            if (i != 1) {
                return "再次随访任务创建失败,再请次重试";
            }
            // 初始化发送方式明细,补偿(compensateTask)和超时判断依赖该表
            patMedInhospService.addServiceSubtaskPreachform(serviceSubtaskAgain, null);
            // 条件更新原任务:0 行说明已被其他请求生成,抛异常回滚本次插入的重复数据
            int updated = serviceSubtaskMapper.updateIsVisitAgainById(serviceSubtask.getId(), 2);
            if (updated != 1) {
                throw new BaseException("无需再次随访,该任务已经再次随访过了");
            }
            return "再次随访任务创建成功";
        } finally {
            unlockAgainTask(serviceSubtask.getId(), lockToken);
        }
    }
    /**
     * 获取二次随访生成锁。Redis 异常时降级为数据库幂等校验,不阻断业务。
     */
    private String tryLockAgainTask(Long subId) {
        String token = UUID.randomUUID().toString();
        try {
            Boolean locked = redisTemplate.opsForValue().setIfAbsent(
                    AGAIN_LOCK_KEY_PREFIX + subId, token, AGAIN_LOCK_SECONDS, TimeUnit.SECONDS);
            return Boolean.TRUE.equals(locked) ? token : null;
        } catch (Exception e) {
            log.warn("再次随访获取Redis锁失败,降级使用数据库幂等校验, subId={}", subId, e);
            return token;
        }
    }
    /**
     * 释放二次随访生成锁,仅释放自己持有的锁。
     */
    private void unlockAgainTask(Long subId, String token) {
        if (token == null) {
            return;
        }
        try {
            String lockKey = AGAIN_LOCK_KEY_PREFIX + subId;
            Object current = redisTemplate.opsForValue().get(lockKey);
            if (token.equals(current)) {
                redisTemplate.delete(lockKey);
            }
        } catch (Exception e) {
            log.warn("再次随访释放Redis锁失败, subId={}", subId, e);
        }
    }
    /**
@@ -2940,7 +3118,7 @@
     * @return
     */
    @Override
    @Cacheable(value = "sfStatistics", key = "T(org.springframework.util.DigestUtils).md5DigestAsHex(#serviceSubtaskCountReq.toString().getBytes())", unless = "#result == null or #result.isEmpty()")
//    @Cacheable(value = "sfStatistics", key = "T(org.springframework.util.DigestUtils).md5DigestAsHex(#serviceSubtaskCountReq.toString().getBytes())", unless = "#result == null or #result.isEmpty()")
    public List<ServiceSubtaskStatistic> getSfStatistics(ServiceSubtaskCountReq serviceSubtaskCountReq) {
        log.info("getSfStatistics的入参为:{}", serviceSubtaskCountReq);
        String drcode = "drcode";
@@ -3062,6 +3240,8 @@
        ssRate.setOrgid(serviceSubtaskCountReq.getOrgid());
        ssRate.setStarttime(serviceSubtaskCountReq.getStartTime());
        ssRate.setEndtime(serviceSubtaskCountReq.getEndTime());
        ssRate.setStartOutHospTime(serviceSubtaskCountReq.getHospitalStartTime());
        ssRate.setEndOutHospTime(serviceSubtaskCountReq.getHospitalEndTime());
        ssRate.setVisitCount(serviceSubtaskCountReq.getVisitCount());
        ssRate.setServiceTypeList(serviceSubtaskCountReq.getServiceType());
        if (serviceSubtaskCountReq.getEndTime() != null && new Date().before(serviceSubtaskCountReq.getEndTime())) {
@@ -3153,6 +3333,8 @@
            if (serviceSubtaskCountReq.getEndTime() != null && new Date().before(serviceSubtaskCountReq.getEndTime())) {
                ss.setEndtime(new Date());
            }
            ss.setStartOutHospTime(serviceSubtaskCountReq.getHospitalStartTime());
            ss.setEndOutHospTime(serviceSubtaskCountReq.getHospitalEndTime());
            Double jsRate = serviceSubtaskMapper.selectTimelyRate(ss);
            statistic.setRate(jsRate);
            if (ObjectUtils.isNotEmpty(statistic)) {
@@ -3305,6 +3487,12 @@
                //应随访人次
                if (serviceSubtask.getSendstate() != null && serviceSubtask.getSendstate() != 4) {
                    serviceSubtaskStatistic.setFollowUpNeeded(serviceSubtaskStatistic.getFollowUpNeeded() + 1L);
                }
                //人工已拨通总量
                if (ObjectUtils.isNotEmpty(serviceSubtask.getIsManuallyCalled())
                        && serviceSubtask.getIsManuallyCalled().equals(1L)) {
                    serviceSubtaskStatistic.setManuallyCalled(serviceSubtaskStatistic.getManuallyCalled() + 1L);
                }
                //首次出院随访
@@ -4326,6 +4514,7 @@
     * taskSituation4Info - taskSituation = 4
     * taskSituation5Info - taskSituation = 5
     * taskSituation6Info - taskSituation = 7
     * manuallyCalledInfo - isManuallyCalled = 1L
     * filterCountList - taskSituation = 6 && sendstate = 4
     *
     */
@@ -4398,7 +4587,7 @@
                serviceSubtaskCountReq.setVisitCount(1);
                serviceSubtaskCountReq.setCurrentPreachform("4");
                break;
            case "wechatInfo":
            case "weChatInfo":
                serviceSubtaskCountReq.setVisitCount(1);
                serviceSubtaskCountReq.setCurrentPreachform("5");
                break;
@@ -4417,7 +4606,7 @@
                serviceSubtaskCountReq.setSendstates(new ArrayList<>(Collections.singletonList(6L)));
                serviceSubtaskCountReq.setCurrentPreachform("4");
                break;
            case "wechatSuccessInfo":
            case "weChatSuccessInfo":
                serviceSubtaskCountReq.setVisitCount(1);
                serviceSubtaskCountReq.setSendstates(new ArrayList<>(Collections.singletonList(6L)));
                serviceSubtaskCountReq.setCurrentPreachform("5");
@@ -4454,7 +4643,7 @@
                serviceSubtaskCountReq.setVisitCount(2);
                serviceSubtaskCountReq.setCurrentPreachform("4");
                break;
            case "wechatAgainInfo":
            case "weChatAgainInfo":
                serviceSubtaskCountReq.setVisitCount(2);
                serviceSubtaskCountReq.setCurrentPreachform("5");
                break;
@@ -4473,7 +4662,7 @@
                serviceSubtaskCountReq.setSendstates(new ArrayList<>(Collections.singletonList(6L)));
                serviceSubtaskCountReq.setCurrentPreachform("4");
                break;
            case "wechatAgainSuccessInfo":
            case "weChatAgainSuccessInfo":
                serviceSubtaskCountReq.setVisitCount(2);
                serviceSubtaskCountReq.setSendstates(new ArrayList<>(Collections.singletonList(6L)));
                serviceSubtaskCountReq.setCurrentPreachform("5");
@@ -4503,6 +4692,9 @@
            case "filterCountList":
                serviceSubtaskCountReq.setTaskSituation(6);
                serviceSubtaskCountReq.setSendstates(new ArrayList<>(Collections.singletonList(4L)));
                break;
            case "manuallyCalledInfo":
                serviceSubtaskCountReq.setIsManuallyCalled(1L);
                break;
            default:
                break;
@@ -5141,12 +5333,6 @@
        String subId = rsaPublicKeyExample.encryptedData(serviceSubtask.getId().toString(), pub_key);
        String taskId = rsaPublicKeyExample.encryptedData(serviceSubtask.getTaskid().toString(), pub_key);
        //丽水中医院发送的是微信公众号
        if (StringUtils.isNotEmpty(serviceSubtask.getOrgid()) && serviceSubtask.getOrgid().equals("47231022633110211A2101")) {
            resultMap = wechatSubTask(subid);
            return resultMap;
        }
        //发送数据的封装
        ServiceOutPath serviceOutPath = new ServiceOutPath();
        serviceOutPath.setParam1(taskId);
@@ -5188,6 +5374,25 @@
                serviceSubtask.setCurrentPreachform("4");
            }
        }
        return resultMap;
    }
    @Override
    public Map<String, Object> weChatSubTask(Long subid) {
        log.info("smsSubTask的入参为:{}", subid);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("code", "500");
        resultMap.put("msg", "发送失败");
        //获取患者的基本信息
        ServiceSubtask serviceSubtask = selectServiceSubtaskById(subid);
        RSAPublicKeyExample rsaPublicKeyExample = new RSAPublicKeyExample();
        String patid = rsaPublicKeyExample.encryptedData(serviceSubtask.getPatid().toString(), pub_key);
        String subId = rsaPublicKeyExample.encryptedData(serviceSubtask.getId().toString(), pub_key);
        String taskId = rsaPublicKeyExample.encryptedData(serviceSubtask.getTaskid().toString(), pub_key);
        //丽水中医院发送的是微信公众号
        resultMap = wechatSubTask(subid);
        return resultMap;
    }
@@ -6137,6 +6342,8 @@
        String voiceText = phoneCallReqYQVO.getAsrtext();
        String questionText = StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrtext()) ? ivrTaskTemplateScriptVO.getIvrtext() : ivrTaskTemplateScriptVO.getScriptContent();
        Integer matched = -1;
        log.info("AI匹配:url = {},questionText = {},voiceText = {},options = {},uuid ={}",
                url,questionText,voiceText,options,uuid);
        matched = matchOptionIndex(url, questionText, voiceText, options, uuid);
        //说明匹配正确了
        if (matched != null && matched >= 0) {
@@ -6230,7 +6437,8 @@
                phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask.getJsy());
                //记录状态
                setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
                return phoneCallBackYQVO;
                back = phoneCallBackYQVO;
                return back;
            }
            flag = 1;
@@ -6238,9 +6446,10 @@
            redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop");
//                        //获取下一题
            log.error("获取下一题的信息:{}", ivrTaskTemplateScriptVO);
            if (ivrTaskTemplateScriptVO.getBranchFlag().equals("1") || ivrTaskTemplateScriptVO.getBranchFlag().equals("0") && ivrTaskTemplateScriptVO.getNextScriptno() != null && ivrTaskTemplateScriptVO.getNextScriptno() != 0) {
            //branchFlag为null时按分支0处理,避免NPE
            if ("1".equals(ivrTaskTemplateScriptVO.getBranchFlag()) || "0".equals(ivrTaskTemplateScriptVO.getBranchFlag()) && ivrTaskTemplateScriptVO.getNextScriptno() != null && ivrTaskTemplateScriptVO.getNextScriptno() != 0) {
                Long nextQuestion = null;
                if (ivrTaskTemplateScriptVO.getBranchFlag().equals("1")) {
                if ("1".equals(ivrTaskTemplateScriptVO.getBranchFlag())) {
                    nextQuestion = chosenOption.getNextQuestion();
                    //更新分数
                    double score = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
@@ -6273,15 +6482,9 @@
                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
                    phoneCallBackYQVO.setType("text");
                    phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask.getJsy());
                    //将结果写进detail表
                    ServiceSubTaskDetailReq ssdReq = new ServiceSubTaskDetailReq();
                    List<ServiceSubtaskDetail> serviceSubtaskDetailList2 = new ArrayList<>();
                    serviceSubtaskDetailList.add(getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate));
                    serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList2);
                    ssdReq.setGuid(phoneCallReqYQVO.getGuid());
                    ssdReq.setOrgid(phoneCallReqYQVO.getOrgid());
                    saveQuestionAnswerPhone(ssdReq);
                    return phoneCallBackYQVO;
                    //明细在本题匹配成功时已落库(见上方 saveQuestionAnswerPhone),这里不再重复保存
                    back = phoneCallBackYQVO;
                    return back;
                }
                for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) {
@@ -6298,6 +6501,15 @@
                        redisCache.deleteObject(phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid());
                    }
                }
                //下一题脚本没找到时,兜底重问当前题,避免调用方误判为未处理而退回正则识别
                if (StringUtils.isEmpty(phoneCallBackYQVO.getValue())) {
                    log.error("下一题脚本未找到,重问当前题,nextQuestion:{}", nextQuestion);
                    phoneCallBackYQVO.setType("text");
                    phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                    phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + getObject(serviceSubtask, questionText));
                }
                back = phoneCallBackYQVO;
                return back;
            } else if (ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getNextScriptno() == 0) {
                ServiceTask serviceTask1 = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
                phoneCallBackYQVO.setType("text");
@@ -6326,33 +6538,101 @@
                //在redis中保存一下结束语,在调用挂电话的方法时删除
                ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
                redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
//                                return phoneCallBackYQVO;
                //结束语已拼进返回值,挂机由平台按返回值执行
                back = phoneCallBackYQVO;
                return back;
            }
        } else {
            log.info("没有匹配上----------------------------");
            //flag=0,说明没 匹配上,也要把患者说的话记录下来
            if (matched == ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().size() - 1 && flag == 0) {
                ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq();
                List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>();
                ServiceSubtaskDetail serviceSubtaskDetail = getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate);
                //修改一下语音路径(改成前端可以访问的,存到数据库中)
                if (StringUtils.isNotEmpty(serviceSubtaskDetail.getQuestionvoice())) {
                    String questionvoice = serviceSubtaskDetail.getQuestionvoice();
                    String[] split = questionvoice.split("\\\\");
                    if (split.length > 0) {
                        String lastPart = split[split.length - 1];
                        serviceSubtaskDetail.setQuestionvoice(voicePathPrefix + lastPart);
            //AI没有匹配上:由AI分支自己按"没问清就重问"的次数处理,不再退回正则识别
            log.info("ai没有匹配上----------------------------");
            //没匹配上也要把患者说的话记录下来(matchedtext置空,与正则路径口径一致)
            ServiceSubTaskDetailReq serviceSubTaskDetailReq = new ServiceSubTaskDetailReq();
            List<ServiceSubtaskDetail> serviceSubtaskDetailList = new ArrayList<>();
            ServiceSubtaskDetail serviceSubtaskDetail = getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate);
            //修改一下语音路径(改成前端可以访问的,存到数据库中)
            if (StringUtils.isNotEmpty(serviceSubtaskDetail.getQuestionvoice())) {
                String questionvoice = serviceSubtaskDetail.getQuestionvoice();
                String[] split = questionvoice.split("\\\\");
                if (split.length > 0) {
                    String lastPart = split[split.length - 1];
                    serviceSubtaskDetail.setQuestionvoice(voicePathPrefix + lastPart);
                }
            }
            serviceSubtaskDetailList.add(serviceSubtaskDetail);
            //如果没有 匹配上,这个必须为null
            serviceSubtaskDetailList.get(0).setMatchedtext("");
            serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList);
            serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid());
            serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid());
            saveQuestionAnswerPhone(serviceSubTaskDetailReq);
            String mateKey = phoneCallReqYQVO.getTaskid().trim() + "&&" + "mate" + "&&" + phoneCallReqYQVO.getUuid();
            Integer count = null;
            Object countObj = redisCache.getCacheObject(mateKey);
            if (ObjectUtils.isNotEmpty(countObj)) count = (Integer) countObj;
            if (count != null && count >= ivrTaskTemplate.getMateNum()) {
                //没匹配次数已经用满,不能再重问了
                boolean noNextQuestion = ("0".equals(ivrTaskTemplateScriptVO.getBranchFlag()) || "1".equals(ivrTaskTemplateScriptVO.getBranchFlag()))
                        && (ivrTaskTemplateScriptVO.getNextScriptno() == null || ivrTaskTemplateScriptVO.getNextScriptno() == 0);
                if (noNextQuestion) {
                    //已经是最后一题,直接挂机
                    ServiceTask serviceTask1 = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
                    phoneCallBackYQVO.setType("text");
                    phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                    phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask1.getJsy());
                    //更新一下分数
                    Double score = null;
                    Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                    if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj;
                    serviceSubtask.setScore(String.valueOf(score));
                    serviceSubtask.setFinishtime(new Date());
                    serviceSubtask.setSendstate(6L);
                    serviceSubtask.setRemark("电话拨打已完成");
                    serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
                    //记录状态
                    setFailPreachForm(serviceSubtask, "3", "电话拨打已完成", "9");
                    //在redis中保存一下结束语,在调用挂电话的方法时删除
                    ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
                    redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES);
                    //去redis中,把该子任务ID删除
                    Long id = serviceSubtask.getId();
                    Map<String, String> map = delRedisValue(null, id.toString());
                    if (ObjectUtils.isNotEmpty(map)) {
                        redisCache.setCacheObject(map.get("cacheName"), map.get("val"));
                        redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone());
                        redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE");
                    }
                } else {
                    //还有下一题,按nextScriptno继续提问
                    for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) {
                        if (script.getSort() == ivrTaskTemplateScriptVO.getNextScriptno().intValue()) {
                            phoneCallBackYQVO.setType("text");
                            phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                            String scriptContent = StringUtils.isNotEmpty(script.getIvrtext()) ? script.getIvrtext() : script.getScriptContent();
                            phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + getObject(serviceSubtask, scriptContent));
                            //将该患者的Redis中的题目ID,进行修改
                            redisCache.setCacheObject(phoneCallReqYQVO.getTaskid().trim() + "-" + phoneCallReqYQVO.getPhone().trim(), script.getId().toString(), 120, TimeUnit.MINUTES);
                            //更新一下分数
                            Double score = null;
                            Object scoreObj = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "SCORE");
                            if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj;
                            score = BigDecimal.valueOf(score).add(new BigDecimal(script.getScore())).doubleValue();
                            redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", score, 120, TimeUnit.MINUTES);
                            //换题成功,没匹配次数清零
                            redisCache.deleteObject(mateKey);
                        }
                    }
                }
                serviceSubtaskDetailList.add(serviceSubtaskDetail);
                //如果没有 匹配上,这个必须为null
                serviceSubtaskDetailList.get(0).setMatchedtext("");
                serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList);
                serviceSubTaskDetailReq.setGuid(phoneCallReqYQVO.getGuid());
                serviceSubTaskDetailReq.setOrgid(phoneCallReqYQVO.getOrgid());
                saveQuestionAnswerPhone(serviceSubTaskDetailReq);
            } else {
                //还没问满次数,用noMatchText引导患者重答
                redisCache.setCacheObject(mateKey, count == null ? 1 : count + 1, 120, TimeUnit.MINUTES);
                phoneCallBackYQVO.setType("text");
                phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue());
                phoneCallBackYQVO.setValue(ivrTaskTemplateScriptVO.getNoMatchText() + getObject(serviceSubtask, StringUtils.isNotEmpty(ivrTaskTemplateScriptVO.getIvrtext()) ? ivrTaskTemplateScriptVO.getIvrtext() : ivrTaskTemplateScriptVO.getScriptContent()));
            }
            back = phoneCallBackYQVO;
            return back;
        }
        return back;
    }