xieb
2023-10-19 1dd5d8f8a616f5cf3caa7828d46989c7d3dcafc4
skjcmanager/skjcmanager-service/skjcmanager-alerts/src/main/java/cn/gistack/alerts/sms/service/impl/SmsServiceImpl.java
@@ -6,19 +6,51 @@
import cn.com.flaginfo.sdk.cmc.api.sms.send.SMSSendDataResult;
import cn.com.flaginfo.sdk.cmc.api.sms.send.SMSSendRequest;
import cn.gistack.alerts.alarmRule.entity.AlarmRecordDetail;
import cn.gistack.alerts.alarmRule.entity.AlarmRule;
import cn.gistack.alerts.alarmRule.service.AlarmRecordDetailService;
import cn.gistack.alerts.alarmRule.vo.AlarmRecordDetailVO;
import cn.gistack.alerts.notice.service.impl.NoticeHandle;
import cn.gistack.alerts.notice.util.FormatUtil;
import cn.gistack.alerts.sms.constant.MinConstant;
import cn.gistack.alerts.sms.dto.DynSMSSendRequestDTO;
import cn.gistack.alerts.sms.entity.SmsRecord;
import cn.gistack.alerts.sms.entity.SmsRequest;
import cn.gistack.alerts.sms.entity.SmsResult;
import cn.gistack.alerts.sms.entity.SmsTemplate;
import cn.gistack.alerts.sms.excel.SendRainSmsExcel;
import cn.gistack.alerts.sms.excel.SendSmsExcel;
import cn.gistack.alerts.sms.service.ISmsRecordService;
import cn.gistack.alerts.sms.service.ISmsResultService;
import cn.gistack.alerts.sms.service.ISmsTemplateService;
import cn.gistack.alerts.sms.service.SmsService;
import cn.gistack.alerts.sms.util.SmsUtils;
import cn.gistack.alerts.sms.vo.SmsRequestTemplate;
import cn.gistack.alerts.sms.vo.SmsResponseVO;
import cn.gistack.alerts.sms.vo.Temp;
import cn.gistack.sm.intelligentCall.entity.CallNotFillRecord;
import cn.gistack.sm.intelligentCall.excel.CallExcel;
import cn.gistack.sm.intelligentCall.feign.OutCallClient;
import cn.gistack.sm.message.entity.MessageRecord;
import cn.gistack.sm.sjztmd.feign.IAttResManagePersonClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.lang.reflect.Array;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static cn.gistack.alerts.sms.util.SmsUtils.validator;
/**
 * 短信发送服务实现层
@@ -37,6 +69,24 @@
   @Autowired
   private ISmsResultService smsResultService;
   @Autowired
   private ISmsTemplateService smsTemplateService;
   @Autowired
   private BladeRedis bladeRedis;
   @Autowired
   private OutCallClient outCallClient;
   @Autowired
   private IAttResManagePersonClient attResManagePersonClient;
   @Autowired
   private SmsAsyncService asyncService;
   @Autowired
   private NoticeHandle noticeHandle;
   /**
    * 发送 xx 变量模板短信
    * @param phoneNumbers 手机号集合
@@ -48,7 +98,7 @@
      List<ComResult<SMSSendDataResult>> list = new ArrayList<>();
      if (phoneNumbers.size()>0){
         // 先保存结果记录
         SmsResult smsResult = saveSendResult(request, phoneNumbers.size());
         SmsResult smsResult = saveSendResult(null,null,request, phoneNumbers.size());
         // 遍历发送
         for (String phone : phoneNumbers) {
            request.setUserNumber(phone);
@@ -56,7 +106,7 @@
            ComResult<SMSSendDataResult> result = SmsUtils.sendMsg(request);
            if(null != smsResult) {
               // 保存记录
               saveSendRecord(request, result.getCode(), result.getMsg(), smsResult.getId());
               saveSendRecord(request, result.getCode().toString(), result.getMsg(), smsResult.getId());
            }
            list.add(result);
         }
@@ -64,83 +114,250 @@
      return list;
   }
//   /**
//    * 发送 具名 变量模板短信(告警定制)-- 动态发送-一个一个发
//    * @param smsRequestTemplate
//    * @return
//    */
//   @Override
//   public Map<String, Object> sendSignMsg(SmsRequestTemplate smsRequestTemplate) {
//      // 取出数据
//      SMSSendRequest request = new SMSSendRequest();
//      SmsTemplate smsTemplate = smsRequestTemplate.getSmsTemplate();
//      AlarmRule alarmRule = smsRequestTemplate.getAlarmRule();
//      request.setTemplateId(smsTemplate.getTemplateId());
//      List<List<String>> templateContent = smsRequestTemplate.getTemplateContent();
//      // 先保存结果记录
//      SmsResult smsResult = saveSendResult(null,null,request, templateContent.size());
//      List<SmsRecord> smsRecordList = new ArrayList<>();
//      List<MessageRecord> messageRecordList = new ArrayList<>();
//      // 遍历处理
//      for (List<String> list : templateContent) {
//         // 设置站内信记录信息
//         MessageRecord messageRecord = new MessageRecord();
//         messageRecord.setTheme(alarmRule.getRuleName());
//         messageRecord.setSender(AuthUtil.getUserId().toString());
//         messageRecord.setSource("智能告警");
//         messageRecord.setStatus(0);
//
//         AlarmRecordDetail alarmRecordDetail = new AlarmRecordDetail();
//         alarmRecordDetail.setReservoirNumber(list.get(0));
//         alarmRecordDetail.setAlarmRecordId(Long.parseLong(list.get(list.size() - 1)));
//         alarmRecordDetail.setAlarmMode("短信");
//         // 删除 最后一个 告警记录id
//         list.remove(list.size() - 1);
//         // 删除 0 水库编码
//         list.remove(0);
//         // 组装数据
//         String row = String.join(",", list);
//         String[] titleArr = smsRequestTemplate.getTitle().split(",");
//         String[][] dyns = new String[2][titleArr.length];
//         dyns[0] = titleArr;
//         dyns[1] = row.split(",");
//         //请求参数
//         ComResult<DynSMSSendDataResult> resultComResult = sendDynSMSSendDataResultComResult(smsTemplate.getTemplateId(), dyns);
//
//         SmsRecord smsRecord = new SmsRecord();
//         if (null != smsResult){
//            alarmRecordDetail.setPhone(list.get(0));
//            // 设置手机号
//            request.setUserNumber(list.get(0));
//            messageRecord.setRecipient(list.get(0));
//            // 内容处理
//            String s = smsTemplate.getContent().replaceAll("\\{.+?\\}", "%s");
//            // 短信内容拼接(完成发送的结果信息)
//            // 需要删除最前面的手机号
//            list.remove(0);
//            // 格式转换
//            String format = String.format(s, list.toArray());
//            // 设置内容
//            request.setMessageContent(format);
//            messageRecord.setContent(format);
//            messageRecordList.add(messageRecord);
//            // 保存短信发送记录
//            smsRecord = saveSendRecord(request, resultComResult.getCode().toString(), resultComResult.getMsg(), smsResult.getId());
//            if (null != smsRecord){
//               alarmRecordDetail.setAlarmContent(format);
//               alarmRecordDetail.setSendRecordId(smsRecord.getId());
//               alarmRecordDetail.setCreateTime(new Date());
//               // 保存告警记录详情信息
//               boolean save = alarmRecordDetailService.save(alarmRecordDetail);
//            }
//         }
//         smsRecordList.add(smsRecord);
//      }
//      if (null!=smsRequestTemplate.getIsSendStation() && smsRequestTemplate.getIsSendStation()) {
//         // 保存站内信信息
//         noticeHandle.saveMessageRecord(messageRecordList);
//      }
//      Map<String, Object> map = new HashMap<>(2);
//      map.put("smsRecord",smsRecordList.size());
//      // 返回
//      return map;
//   }
   /**
    * 发送 具名 变量模板短信
    * 发送 具名 变量模板短信(告警定制)--动态批量发送
    * @param smsRequestTemplate
    * @return
    */
   @Override
   public Object sendSignMsg(SmsRequestTemplate smsRequestTemplate) {
   public Map<String, Object> sendSignMsg(SmsRequestTemplate smsRequestTemplate) {
      // 取出数据
      SMSSendRequest request = new SMSSendRequest();
      SmsTemplate smsTemplate = smsRequestTemplate.getSmsTemplate();
      request.setTemplateId(smsTemplate.getTemplateId());
      List<List<String>> templateContent = smsRequestTemplate.getTemplateContent();
      // 先保存结果记录
      SmsResult smsResult = saveSendResult(request, templateContent.size());
      // 是否同时发送站内信
      Boolean isSendStation = false;
      if (null!=smsRequestTemplate.getIsSendStation()){
         isSendStation = smsRequestTemplate.getIsSendStation();
      }
      // 判断 templateContent 个数,个数超过1000 需要分段发送短信
      List<List<List<String>>> lists = Lists.partition(templateContent, 1000);
      int number = 0;
      for (List<List<String>> list : lists) {
         // 临时保存告警记录用
         List<List<String>> templateList = getAlarmList(list);
         // 批量发送短信
         Map<String, Object> map = batchSendAlertsSms(smsRequestTemplate.getSmsTemplate(), list);
         int count = Integer.parseInt(map.get("errCount").toString());
         ComResult<DynSMSSendDataResult> resultComResult =(ComResult<DynSMSSendDataResult>) map.get("resultComResult");
         // 保存短信结果记录
         SmsResult smsResult = saveSendResult(resultComResult.getCode().toString(),resultComResult.getMsg(),request, list.size() - count);
         // 保存详情记录(短信详情,告警详情)
         List<SmsRecord> smsRecordList = saveAlertsAndSmsDetail(smsResult,resultComResult,smsRequestTemplate.getSmsTemplate(),
            templateList,request,smsRequestTemplate.getAlarmRule(),isSendStation);
         // number 累加
         number += smsRecordList.size();
      }
      // 设置返回数据
      Map<String, Object> params = new HashMap<>(1);
      params.put("sendNumber",number);
      // 返回
      return params;
   }
   /**
    * 获取用户告警的集合
    * @param list
    * @return
    */
   private List<List<String>> getAlarmList(List<List<String>> list) {
      List<List<String>> arrayList = new ArrayList<>();
      // 值引用
      for (List<String> stringList : list) {
         List<String> child = new ArrayList<>();
         child.addAll(stringList);
         arrayList.add(child);
      }
      // 返回
      return arrayList;
   }
   /**
    * 保存详情记录(短信详情,告警详情)
    * @param smsResult
    * @param resultComResult
    * @param smsTemplate
    * @param templateContent
    * @param request
    * @param request
    * @param request
    * @return
    */
   private List<SmsRecord> saveAlertsAndSmsDetail(SmsResult smsResult,
                              ComResult<DynSMSSendDataResult> resultComResult,
                              SmsTemplate smsTemplate,
                              List<List<String>> templateContent,
                              SMSSendRequest request,
                              AlarmRule alarmRule,
                              Boolean isSendStation) {
      List<SmsRecord> smsRecordList = new ArrayList<>();
      List<MessageRecord> messageRecordList = new ArrayList<>();
      // 遍历处理
      for (List<String> list : templateContent) {
         AlarmRecordDetail alarmRecordDetail = new AlarmRecordDetail();
         alarmRecordDetail.setReservoirNumber(list.get(0));
         alarmRecordDetail.setAlarmRecordId(Long.parseLong(list.get(list.size() - 1)));
         alarmRecordDetail.setAlarmMode("短信");
         // 校验手机号,发送短信时已校验
         if (validator(list.get(1))) {
            // 设置站内信记录信息
            MessageRecord messageRecord = new MessageRecord();
            messageRecord.setTheme(alarmRule.getRuleName());
            messageRecord.setSender(AuthUtil.getUserId().toString());
            messageRecord.setSource("智能告警");
            messageRecord.setStatus(0);
            // 设置告警记录信息
            AlarmRecordDetail alarmRecordDetail = new AlarmRecordDetail();
            alarmRecordDetail.setReservoirNumber(list.get(0));
            alarmRecordDetail.setAlarmRecordId(Long.parseLong(list.get(list.size() - 1)));
            alarmRecordDetail.setAlarmMode("短信");
            // 删除 最后一个 告警记录id
            list.remove(list.size() - 1);
            // 删除 0 水库编码
            list.remove(0);
            SmsRecord smsRecord = new SmsRecord();
            if (null != smsResult) {
               alarmRecordDetail.setPhone(list.get(0));
               messageRecord.setRecipient(list.get(0));
               // 设置手机号
               request.setUserNumber(list.get(0));
               // 内容处理
               String s = smsTemplate.getContent().replaceAll("\\{.+?\\}", "%s");
               // 短信内容拼接(完成发送的结果信息)
               // 需要删除最前面的手机号
               list.remove(0);
               // 格式转换
               String format = String.format(s, list.toArray());
               // 设置内容
               request.setMessageContent(format);
               messageRecord.setContent(format);
               messageRecordList.add(messageRecord);
               // 保存短信发送记录
               smsRecord = saveSendRecord(request, resultComResult.getCode().toString(), resultComResult.getMsg(), smsResult.getId());
               if (null != smsRecord) {
                  alarmRecordDetail.setAlarmContent(format);
                  alarmRecordDetail.setSendRecordId(smsRecord.getId());
                  alarmRecordDetail.setCreateTime(new Date());
                  // 保存告警记录详情信息
                  boolean save = alarmRecordDetailService.save(alarmRecordDetail);
               }
            }
            smsRecordList.add(smsRecord);
         }
      }
      if (isSendStation) {
         // 保存站内信信息
         noticeHandle.saveMessageRecord(messageRecordList);
      }
      // 返回
      return smsRecordList;
   }
   /**
    * 批量发送告警短信
    * @param smsTemplate
    * @param templateContent
    */
   private Map<String, Object> batchSendAlertsSms(SmsTemplate smsTemplate, List<List<String>> templateContent) {
      Map<String, Object> map = new HashMap<>(2);
      int count = 0;
      StringBuilder builder = new StringBuilder();
      // 拼接短信标题数组
      String [] titleArr = getSmsTitleArr(smsTemplate);
      // 遍历,拼接短信
      for (List<String> list : templateContent) {
         // 删除 最后一个 告警记录id
         list.remove(list.size() - 1);
         // 删除 0 水库编码
         list.remove(0);
         // 转换字符串
         String row = String.join(",", list);
         // 组装数据
         String[][] dyns = new String[][]{{smsRequestTemplate.getTitle()}, {row}};
         //请求参数
         DynSMSSendRequest sendRequest = new DynSMSSendRequest();
         sendRequest.setTemplateId(smsTemplate.getTemplateId());
         sendRequest.setDynData(dyns);
         // 发送
         ComResult<DynSMSSendDataResult> resultComResult = SmsUtils.dynSendMethod(sendRequest);
         SmsRecord smsRecord = new SmsRecord();
         if (null != smsResult){
            alarmRecordDetail.setPhone(list.get(0));
            // 设置手机号
            request.setUserNumber(list.get(0));
            // 内容处理
            String s = smsTemplate.getContent().replaceAll("\\{.+?\\}", "%s");
            // 短信内容拼接(完成发送的结果信息)
            // 需要删除最前面的手机号
            list.remove(0);
            // 格式转换
            String format = String.format(s, list.toArray());
            // 设置内容
            request.setMessageContent(format);
            // 保存记录
            smsRecord = saveSendRecord(request, resultComResult.getCode(), resultComResult.getMsg(), smsResult.getId());
            if (null != smsRecord){
               alarmRecordDetail.setAlarmContent(format);
               alarmRecordDetail.setSendRecordId(smsRecord.getId());
               alarmRecordDetail.setCreateTime(new Date());
               // 保存告警记录详情信息
               boolean save = alarmRecordDetailService.save(alarmRecordDetail);
            }
         String join = String.join(",", list);
         // 转换,校验手机号码
         if (validator(list.get(0))){
            builder.append(join).append(";");
         }else {
            count++;
         }
         smsRecordList.add(smsRecord);
      }
      Map<String, Object> map = new HashMap<>(2);
      map.put("smsRecord",smsRecordList);
      map.put("smsResult",smsResult);
      // 返回
      return map;
   }
   /**
    * 发送 具名 变量模板短信--批量一次发送
    * @param title 具名变量头
    * @return
    */
   public Object sendSignMsg(String title, String datas, SMSSendRequest request, Integer type, SmsTemplate smsTemplate) {
      String[] titleArr = title.split(",");
      String datas = builder.toString();
      String[] rows = datas.split(";");
      String[][] dyns = new String[rows.length + 1][titleArr.length];
      dyns[0] = titleArr;
@@ -150,38 +367,66 @@
         dyns[rowNum++] = cols;
      }
      //请求参数
      DynSMSSendRequest sendRequest = new DynSMSSendRequest();
      sendRequest.setTemplateId(request.getTemplateId());
      sendRequest.setDynData(dyns);
      // 发送
      ComResult<DynSMSSendDataResult> resultComResult = SmsUtils.dynSendMethod(sendRequest);
      // 先保存结果记录
      SmsResult smsResult = saveSendResult(request, rows.length);
      SmsRecord smsRecord = new SmsRecord();
      if (null != smsResult){
         // 保存记录
         smsRecord = saveSendRecord(request, resultComResult.getCode(), resultComResult.getMsg(), smsResult.getId());
      }
      Map<String, Object> map = new HashMap<>(2);
      map.put("smsRecord",smsRecord);
      map.put("smsResult",smsResult);
      // 返回
      ComResult<DynSMSSendDataResult> resultComResult = sendDynSMSSendDataResultComResult(smsTemplate.getTemplateId(), dyns);
      map.put("resultComResult",resultComResult);
      map.put("errCount",count);
      //返回
      return map;
   }
   /**
    * 发送降雨短信--批量一次发送
    * @param params 具名变量头
    * @return
    */
   @Override
   public Object sendSignRainMsg(Map<String, Object> params) {
      String[] titleArr = params.get("title").toString().split(",");
      String data = params.get("data").toString();
      String templateId = params.get("templateId").toString();
      // 查询短信模板
      SmsTemplate smsTemplate = smsTemplateService.getOne(new QueryWrapper<SmsTemplate>().eq("template_id", templateId));
      List<String> phones = (List<String>)params.get("phones");
      List<String> errPhones = new ArrayList<>();
      // 手机号去重
      Set<String> hashSet = new HashSet<>();
      for (String phone : phones) {
         hashSet.add(phone);
      }
      // 分割
      List<List<String>> partition = Lists.partition(new ArrayList<>(hashSet), 1000);
      int errNumber = 0;
      // 遍历
      for (List<String> list : partition) {
         // 批量发送短信
         Map<String, Object> batchSendSmsMap = batchSendSms(new HashSet<>(list), titleArr, data, smsTemplate,errPhones);
         errPhones = (List<String>) batchSendSmsMap.get("errPhones");
         errNumber += errPhones.size();
      }
      // 计算差值
      Integer diff = phones.size() - hashSet.size();
      String successMsg = "发送成功!共提交号码 "+phones.size()+" 个,其中重复号码 "+diff+" 个,错误号码 "
         + errNumber +" 个,发送成功号码 "+ (hashSet.size()-errNumber) + " 个。";
      // 返回
      return R.data(200,successMsg,null);
   }
   /**
    * 发送记录保存
    * @param code 响应消息code
    * @param msg 响应消息
    * @param request 发送信息
    * @param number 号码个数
    */
   @Override
   public SmsResult saveSendResult(SMSSendRequest request,Integer number) {
   public SmsResult saveSendResult(String code,String msg, SMSSendRequest request, Integer number) {
      // 先保存结果表
      SmsResult smsResult = new SmsResult();
      smsResult.setTemplateId(request.getTemplateId());
      smsResult.setContent(request.getMessageContent());
      smsResult.setNumber(number);
      smsResult.setResCode(code);
      smsResult.setResMsg(msg);
      //插入记录
      boolean save = smsResultService.save(smsResult);
      if (save){
@@ -200,18 +445,626 @@
    * @param resultId
    */
   @Override
   public SmsRecord saveSendRecord(SMSSendRequest request, Integer code, String sendMsg, Long resultId) {
   public SmsRecord saveSendRecord(SMSSendRequest request, String code, String sendMsg, Long resultId) {
      // 在保存明细
      SmsRecord smsRecord = new SmsRecord();
      smsRecord.setTel(request.getUserNumber());
      smsRecord.setContent(request.getMessageContent());
      smsRecord.setTemplateId(request.getTemplateId());
      smsRecord.setResultId(resultId);
      smsRecord.setResponseStatus(code.toString());
      smsRecord.setResponseStatus(code);
      smsRecord.setResponseMsg(sendMsg);
      //插入记录
      smsRecordService.save(smsRecord);
      // 返回
      return smsRecord;
   }
   /**
    * 外呼未接通-发送短信
    * @param taskId
    * @param time
    * @return
    */
   @Override
   public String sendSmsByOutCallNotConnect(String taskId,String time) {
      String templateId = "2431012249882";
      // 查询符合当前时间外呼任务id集合
      String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
      List<String> taskIdList = smsTemplateService.getTaskIdListByTime(format);
      if (taskIdList.size()>0) {
         // 查询当前任务未接通的人员信息(包含水库编号)
         List<Map<String, Object>> list = smsTemplateService.getNotConnectPatrolPersonList(taskIdList, null);
         SmsTemplate smsTemplate = smsTemplateService.getOne(new QueryWrapper<SmsTemplate>().eq("template_id", templateId));
         if (list.size() > 0) {
            List<Map<String, Object>> newList = new ArrayList<>();
            // 比对
            for (Map<String, Object> map : list) {
               // 获取任务id
               String redisByTaskId = bladeRedis.get(MinConstant.is_send_prefix + map.get("callId").toString());
               // 如果为null,并且不能匹配,加入发送短信集合
               if (redisByTaskId == null) {
                  newList.add(map);
               }
            }
            if (newList.size() > 0) {
               // 组装短信数据
               StringBuilder builder = new StringBuilder();
               // 遍历
               for (Map<String, Object> map : newList) {
                  builder.append(map.get("userPhone") + ",")
                     .append(time + ",")
                     .append(map.get("waterName") + ",")
                     .append(MinConstant.fillWaterInfoUrl + "?" + "callId=" + map.get("callId"))
                     .append(";");
               }
               String datas = builder.toString();
               String title = "手机号码,时间范围,水库名称,访问链接";
               String[] titleArr = title.split(",");
               String[] rows = datas.split(";");
               String[][] dyns = new String[rows.length + 1][titleArr.length];
               dyns[0] = titleArr;
               int rowNum = 1;
               for (String row : rows) {
                  String[] cols = row.split(",");
                  dyns[rowNum++] = cols;
               }
               ComResult<DynSMSSendDataResult> resultComResult = sendDynSMSSendDataResultComResult(templateId, dyns);
               SmsResult smsResult = getSaveSmsResult(resultComResult.getCode().toString(),resultComResult.getMsg(),templateId, rows);
               if (null != smsResult) {
                  List<SmsRecord> smsRecordList = new ArrayList<>();
                  Pattern compile = Pattern.compile("[^0-9]");
                  Integer result = Integer.parseInt(compile.matcher(time).replaceAll("").trim());
                  // 分钟或小时
                  Long validTime = time.contains("分钟") ? 60L * result : 60L * 60 * result;
                  // 遍历保存
                  for (Map<String, Object> map : newList) {
                     // 保存redis
                     // 已发送短信的人员对应呼叫id的过期时间
                     bladeRedis.setEx(MinConstant.is_send_prefix + map.get("callId").toString(),  map.get("taskId").toString(), MinConstant.is_send_time);
                     // 填报过期时间
                     bladeRedis.setEx(MinConstant.fill_info_prefix + map.get("callId").toString(), map.get("taskId").toString(), validTime);
                     // 封装短息记录数据
                     SmsRecord smsRecord = getSmsRecord(time, templateId, smsTemplate, resultComResult, smsResult, map);
                     // 加入集合
                     smsRecordList.add(smsRecord);
                  }
                  // 批量保存记录
                  Integer count = smsRecordService.batchSaveSendRecord(smsRecordList);
                  // 返回
                  return count.toString();
               }
            }
         }
      }
      return null;
   }
   /**
    * 保存短信发送结果
    * @param code
    * @param msg
    * @param templateId
    * @param rows
    * @return
    */
   private SmsResult getSaveSmsResult(String code,String msg,String templateId, String[] rows) {
      SMSSendRequest request = new SMSSendRequest();
      request.setTemplateId(templateId);
      // 先保存结果记录
      return saveSendResult(code,msg,request, rows.length);
   }
   /**
    * 动态批量发送短信
    * @param templateId
    * @param dyns
    * @return
    */
   private ComResult<DynSMSSendDataResult> sendDynSMSSendDataResultComResult(String templateId, String[][] dyns) {
      //请求参数
      DynSMSSendRequestDTO sendRequest = new DynSMSSendRequestDTO();
//      DynSMSSendRequest sendRequest = new DynSMSSendRequest();
      // 相同号码,不同内容,不需要去重处理
      sendRequest.setDuplicateRemoval("1");
      sendRequest.setTemplateId(templateId);
      sendRequest.setDynData(dyns);
      // 发送
      return SmsUtils.dynSendMethod(sendRequest);
   }
   /**
    * 短信记录数据处理
    * @param time
    * @param templateId
    * @param smsTemplate
    * @param resultComResult
    * @param smsResult
    * @param map
    * @return
    */
   @NotNull
   private SmsRecord getSmsRecord(String time, String templateId, SmsTemplate smsTemplate, ComResult<DynSMSSendDataResult> resultComResult, SmsResult smsResult, Map<String, Object> map) {
      SmsRecord smsRecord = new SmsRecord();
      smsRecord.setId(IdWorker.getId());
      smsRecord.setTel(map.get("userPhone").toString());
      // 内容处理
      String s = smsTemplate.getContent().replaceAll("\\{.+?\\}", "%s");
      // 拼接内容
      String arrString = time + "," +
         map.get("waterName").toString() + "," +
         MinConstant.fillWaterInfoUrl + "?" + "callId=" + map.get("callId") ;
      // 格式转换
      String format = String.format(s, arrString.split(","));
      smsRecord.setContent(format);
      smsRecord.setTemplateId(templateId);
      smsRecord.setResultId(smsResult.getId());
      smsRecord.setResponseStatus(resultComResult.getCode().toString());
      smsRecord.setResponseMsg(resultComResult.getMsg());
      // 返回
      return smsRecord;
   }
   /**
    * 通过手机号获取外呼未接通已发短信通知的人员水库信息
    * @param callId 呼叫id
    * @return
    */
   @Override
   public Object getCallNotConnectSmsNoticeInfo(String callId) {
      Map<String, Object> map = new HashMap<>(2);
      boolean flag = false;
      List<Map<String, Object>> list = new ArrayList<>();
      // 通过手机号查询外呼任务id
      String taskId = bladeRedis.get(MinConstant.is_send_prefix + callId);
      // 判断
      if (null!=taskId && !taskId.equals("")){
         List<String> taskIdList = new ArrayList<>();
         taskIdList.add(taskId);
         // 通过手机号和外呼任务id 查询水库人员信息
         list = smsTemplateService.getNotConnectPatrolPersonList(taskIdList,callId);
         // 查询是否填报
         CallNotFillRecord callNotFillRecordInfo = outCallClient.getCallNotFillRecordInfo(callId);
         if (callNotFillRecordInfo != null){
            flag = true;
         }
         // 封装数据
         map.put("list",list);
         map.put("isFill",flag);
         // 返回
         return map;
      }
      // 没有,已过期
      return map;
   }
   /**
    * 导入表格发送降雨短信
    * @param list 导入的excel 集合数据
    * @param startTime 短信内容填报起始时间
    * @param endTime 短信内容填报截止时间
    * @return
    */
   @Override
   public Object importSendRainSms(List<SendRainSmsExcel> list,String startTime,String endTime) {
      String templateId = "2431012251309";
      // 获取水库个数
      Integer size = list.size();
      List<String> errPhones = new ArrayList<>();
      // 转换
      List<String> stringList = list.stream().map(SendRainSmsExcel::getWaterCode).collect(Collectors.toList());
      // 通过水库代码获取巡查责任人及技术责任人手机号
      Set<String> personList = attResManagePersonClient.getPersonListByWaterCodeList(stringList);
      // 查询短信模板
      SmsTemplate smsTemplate = smsTemplateService.getOne(new QueryWrapper<SmsTemplate>().eq("template_id", templateId));
      String param = startTime + "-" + endTime;
      // 拼接短信标题数组
      String [] titleArr = getSmsTitleArr(smsTemplate);
      // 分割
      List<List<String>> partition = Lists.partition(new ArrayList<>(personList), 1000);
      int errNumber = 0;
      ComResult<DynSMSSendDataResult> resultComResult = new ComResult();
      // 遍历
      for (List<String> list1 : partition) {
         // 批量发送短信
         Map<String, Object> batchSendSmsMap = batchSendSms(new HashSet<>(list1), titleArr, param, smsTemplate,errPhones);
         resultComResult = (ComResult<DynSMSSendDataResult>)batchSendSmsMap.get("resultComResult");
         errPhones = (List<String>) batchSendSmsMap.get("errPhones");
         errNumber += errPhones.size();
      }
      // 计算差值
      Integer diff = personList.size() - errNumber;
      if (resultComResult.getCode()==0){
         String successMsg = "发送成功!共导入水库个数 "+ size +" 个,其中发送号码 "+ diff + " 个。";
         // 返回
         return R.data(200,successMsg,null);
      }
      String errorMsg = "发送失败!共导入水库个数 "+ size +" 个,发送异常号码 "+ diff + " 个,异常原因" + resultComResult.getMsg() + "。";
      // 返回
      return R.data(400,errorMsg,null);
   }
   /**
    * 拼接短信标题数组
    * @param smsTemplate
    * @return
    */
   private String[] getSmsTitleArr(SmsTemplate smsTemplate) {
      String title = FormatUtil.composeMessage(smsTemplate.getContent());
      // 返回
      return title.split(",");
   }
   /**
    * 批量发送动态短信--该方法只适合除手机号外只有一个动态参数并且是内容一致的情况
    * @param phoneList
    * @param titleArr 示例: [手机号码,水库名称,水位值]
    * @param param 示例: ***水库,15.12
    * @param smsTemplate
    * @return
    */
   private Map<String, Object> batchSendSms(Set<String> phoneList,String[] titleArr,String param,SmsTemplate smsTemplate,List<String> errPhones){
      Map<String, Object> map = new HashMap<>();
      StringBuilder builder = new StringBuilder();
      // 遍历,拼接短信
      if (phoneList.size()>0){
         for (String phone : phoneList) {
            if (validator(phone)){
               builder.append(phone+","+ param).append(";");
            }else {
               // 异常手机号
               errPhones.add(phone);
            }
         }
      }
      String datas = builder.toString();
      String[] rows = datas.split(";");
      String[][] dyns = new String[rows.length + 1][titleArr.length];
      dyns[0] = titleArr;
      int rowNum = 1;
      for (String row : rows) {
         String[] cols = row.split(",");
         dyns[rowNum++] = cols;
      }
      //请求发送短信
      ComResult<DynSMSSendDataResult> resultComResult = sendDynSMSSendDataResultComResult(smsTemplate.getTemplateId(), dyns);
      // 保存发送结果
      SmsResult smsResult = getSaveSmsResult(resultComResult.getCode().toString(),resultComResult.getMsg(),smsTemplate.getTemplateId(), rows);
      // 异步记录发送记录
      asyncService.batchSaveSendRecord(smsResult,rows,smsTemplate,resultComResult);
      // 返回
      map.put("errPhones",errPhones);
      map.put("resultComResult",resultComResult);
      return map;
   }
   /**
    * 发送待办提醒短信
    * @param list
    */
   @Override
   public void sendEmailMsg(List<String> list, SmsRequest smsRequest) {
      String templateId = "2431012165299";
      // 获取水库个数
      List<String> errPhones = new ArrayList<>();
      // 去重
      Set<String> hashSet = new HashSet<>(list);
      // 查询短信模板
      SmsTemplate smsTemplate = smsTemplateService.getOne(new QueryWrapper<SmsTemplate>().eq("template_id", templateId));
      String param = smsRequest.getContent();
      // 拼接短信标题数组
      String [] titleArr = getSmsTitleArr(smsTemplate);
      // 批量发送短信
      Map<String, Object> batchSendSmsMap = batchSendSms(hashSet, titleArr, param, smsTemplate,errPhones);
   }
   /**
    * 发送合并水库名短信
    * @param smsRequestTemplate
    */
   @Override
   public void sendMergeSignMsg(SmsRequestTemplate smsRequestTemplate) {
      // 取出数据
      SMSSendRequest request = new SMSSendRequest();
      SmsTemplate smsTemplate = smsRequestTemplate.getSmsTemplate();
      request.setTemplateId(smsTemplate.getTemplateId());
      List<List<String>> templateContent = smsRequestTemplate.getTemplateContent();
      List<Temp> tempList = new ArrayList<>();
      // 合并数据
      for (List<String> list : templateContent) {
         Temp temp = new Temp();
         temp.setPhone(list.get(1));
         temp.setReservoirCode(list.get(0));
         temp.setReservoirName(list.get(3));
         temp.setAlarmRecordId(list.get(list.size()-1));
         // 放入临时集合
         tempList.add(temp);
      }
      // 按手机号分组
      Map<String, List<Temp>> listMap = tempList.stream().collect(Collectors.groupingBy(Temp::getPhone));
      // 遍历 map 发送短信
      listMap.forEach((s, temps) -> {
         StringBuilder builder = new StringBuilder();
         StringBuilder smsRecordBuilder = new StringBuilder();
         builder.append(s).append(",");
         // 如果一人对应水库数量超过30个,则分批发送
         List<List<Temp>> lists = Lists.partition(new ArrayList<>(temps), 30);
         for (List<Temp> list : lists) {
            List<AlarmRecordDetailVO> alarmRecordDetailList = new ArrayList<>();
            // 遍历
            for (Temp temp : list) {
               builder.append(temp.getReservoirName()).append(",");
               smsRecordBuilder.append(temp.getReservoirName()).append(",");
               AlarmRecordDetailVO alarmRecordDetail = new AlarmRecordDetailVO();
               alarmRecordDetail.setReservoirNumber(temp.getReservoirCode());
               alarmRecordDetail.setAlarmRecordId(Long.parseLong(temp.getAlarmRecordId()));
               alarmRecordDetail.setAlarmMode("短信");
               alarmRecordDetail.setPhone(temp.getPhone());
               alarmRecordDetail.setReservoirName(temp.getReservoirName());
               // 加入集合
               alarmRecordDetailList.add(alarmRecordDetail);
            }
            String row = builder.substring(0, builder.length() - 1);
            // 组装数据
            String[] titleArr = smsRequestTemplate.getTitle().split(",");
            String[][] dyns = new String[2][titleArr.length];
            dyns[0] = titleArr;
            dyns[1] = row.split(",");
            //请求参数
            ComResult<DynSMSSendDataResult> resultComResult = sendDynSMSSendDataResultComResult(smsTemplate.getTemplateId(), dyns);
            // 先保存结果记录
            SmsResult smsResult = saveSendResult(resultComResult.getCode().toString(),resultComResult.getMsg(),request, 1);
            // 设置手机号
            request.setUserNumber(s);
            // 内容处理
            String str = smsTemplate.getContent().replaceAll("\\{.+?\\}", "%s");
            // 短信内容拼接(完成发送的结果信息)
            String substring = smsRecordBuilder.substring(0, smsRecordBuilder.length() - 1);
            // 格式转换
            String format = String.format(str, substring.split(","));
            // 设置内容
            request.setMessageContent(format);
            // 保存短信发送记录
            SmsRecord smsRecord = saveSendRecord(request, resultComResult.getCode().toString(), resultComResult.getMsg(), smsResult.getId());
            //保存告警记录详情信息
            if (null != smsRecord) {
               List<AlarmRecordDetail> alarmRecordDetailArrayList = new ArrayList<>();
               for (AlarmRecordDetailVO alarmRecordDetail : alarmRecordDetailList) {
                  AlarmRecordDetail alarmRecordDetail1 = new AlarmRecordDetail();
                  // 短信内容拼接(完成发送的结果信息)
                  String formatContent = String.format(str, alarmRecordDetail.getReservoirName().split(","));
                  alarmRecordDetail1.setAlarmContent(formatContent);
                  alarmRecordDetail1.setSendRecordId(smsRecord.getId());
                  alarmRecordDetail1.setCreateTime(new Date());
                  alarmRecordDetail1.setReservoirNumber(alarmRecordDetail.getReservoirNumber());
                  alarmRecordDetail1.setAlarmRecordId(alarmRecordDetail.getAlarmRecordId());
                  alarmRecordDetail1.setAlarmMode(alarmRecordDetail.getAlarmMode());
                  alarmRecordDetail1.setPhone(alarmRecordDetail.getPhone());
                  alarmRecordDetailArrayList.add(alarmRecordDetail1);
               }
               // 保存告警记录详情信息
               boolean save = alarmRecordDetailService.saveBatch(alarmRecordDetailArrayList);
            }
         }
      });
   }
//   /**
//    * 发送合并水库名短信
//    * @param smsRequestTemplate
//    */
//   @Override
//   public void sendMergeSignMsg(SmsRequestTemplate smsRequestTemplate) {
//      // 取出数据
//      SMSSendRequest request = new SMSSendRequest();
//      SmsTemplate smsTemplate = smsRequestTemplate.getSmsTemplate();
//      request.setTemplateId(smsTemplate.getTemplateId());
//      List<List<String>> templateContent = smsRequestTemplate.getTemplateContent();
//      List<Temp> tempList = new ArrayList<>();
//      // 合并数据
//      for (List<String> list : templateContent) {
//         Temp temp = new Temp();
//         temp.setPhone(list.get(1));
//         temp.setReservoirCode(list.get(0));
//         temp.setReservoirName(list.get(3));
//         temp.setAlarmRecordId(list.get(list.size()-1));
//         // 放入临时集合
//         tempList.add(temp);
//      }
//      // 按手机号分组
//      Map<String, List<Temp>> listMap = tempList.stream().collect(Collectors.groupingBy(Temp::getPhone));
//      // 短信发送行数据
//      List<String> rowList = new ArrayList<>();
//      // 告警记录详情数据
//      List<AlarmRecordDetailVO> alarmRecordDetailList = new ArrayList<>();
//      // 遍历 map 发送短信,组装数据
//      listMap.forEach((s, temps) -> {
//         StringBuilder builder = new StringBuilder();
//         StringBuilder smsRecordBuilder = new StringBuilder();
//         builder.append(s).append(",");
//         // 如果一人对应水库数量超过30个,则分批发送
//         List<List<Temp>> lists = Lists.partition(new ArrayList<>(temps), 30);
//         for (List<Temp> list : lists) {
//            // 遍历
//            for (Temp temp : list) {
//               builder.append(temp.getReservoirName()).append(",");
//               smsRecordBuilder.append(temp.getReservoirName()).append(",");
//               AlarmRecordDetailVO alarmRecordDetail = new AlarmRecordDetailVO();
//               alarmRecordDetail.setReservoirNumber(temp.getReservoirCode());
//               alarmRecordDetail.setAlarmRecordId(Long.parseLong(temp.getAlarmRecordId()));
//               alarmRecordDetail.setAlarmMode("短信");
//               alarmRecordDetail.setPhone(temp.getPhone());
//               alarmRecordDetail.setReservoirName(temp.getReservoirName());
//               // 加入集合
//               alarmRecordDetailList.add(alarmRecordDetail);
//            }
//            String row = builder.substring(0, builder.length() - 1);
//            rowList.add(row);
//         }
//      });
//      // 批量发送短信
//      mergeBatchSendSms(smsRequestTemplate,request,smsTemplate,rowList,alarmRecordDetailList);
//   }
   /**
    * 批量发送合并水库的短信
    */
   public void mergeBatchSendSms(SmsRequestTemplate smsRequestTemplate,
                          SMSSendRequest request,
                          SmsTemplate smsTemplate,
                          List<String> rowList,
                          List<AlarmRecordDetailVO> alarmRecordDetailList) {
      // 组装数据
      String[] titleArr = smsRequestTemplate.getTitle().split(",");
      String[][] dyns = new String[rowList.size() + 1][titleArr.length];
      dyns[0] = titleArr;
      int rowNum = 1;
      for (String row : rowList) {
         String[] cols = row.split(",");
         dyns[rowNum++] = cols;
      }
      //请求参数
      ComResult<DynSMSSendDataResult> resultComResult = sendDynSMSSendDataResultComResult(smsTemplate.getTemplateId(), dyns);
      // 先保存结果记录
      SmsResult smsResult = saveSendResult(resultComResult.getCode().toString(),resultComResult.getMsg(),request, rowList.size());
      List<AlarmRecordDetail> alarmRecordDetailArrayList = new ArrayList<>();
      // 遍历
      for (AlarmRecordDetailVO alarmRecordDetailVO : alarmRecordDetailList) {
         // 设置手机号
         request.setUserNumber(alarmRecordDetailVO.getPhone());
         // 内容处理
         String str = smsTemplate.getContent().replaceAll("\\{.+?\\}", "%s");
         // 格式转换
         String formatContent = String.format(str, alarmRecordDetailVO.getReservoirName().split(","));
         // 设置内容
         request.setMessageContent(formatContent);
         // 保存短信发送记录
         SmsRecord smsRecord = saveSendRecord(request, resultComResult.getCode().toString(), resultComResult.getMsg(), smsResult.getId());
         AlarmRecordDetail alarmRecordDetail1 = new AlarmRecordDetail();
         // 短信内容拼接(完成发送的结果信息)
         alarmRecordDetail1.setAlarmContent(formatContent);
         alarmRecordDetail1.setSendRecordId(smsRecord.getId());
         alarmRecordDetail1.setCreateTime(new Date());
         alarmRecordDetail1.setReservoirNumber(alarmRecordDetailVO.getReservoirNumber());
         alarmRecordDetail1.setAlarmRecordId(alarmRecordDetailVO.getAlarmRecordId());
         alarmRecordDetail1.setAlarmMode(alarmRecordDetailVO.getAlarmMode());
         alarmRecordDetail1.setPhone(alarmRecordDetailVO.getPhone());
         alarmRecordDetailArrayList.add(alarmRecordDetail1);
      }
      // 保存告警记录详情信息
      boolean save = alarmRecordDetailService.saveBatch(alarmRecordDetailArrayList);
   }
   /**
    * 批量发送短信(集合数据)
    * @param map (保护参数 1:短信模板id  2:数据集合 list<Map<String,Object>>)
    * @return
    */
   @Override
   public Object batchSendSms(Map<String, Object> map) {
      // 获取模板id
      String templateId = map.get("templateId").toString();
      // 获取手机号集合
      List<String> list = (List<String>) map.get("phones");
      // 获取发送的动态内容(msg)
      String param = (String) map.get("content");
      // 创建错误手机号集合
      List<String> errPhones = new ArrayList<>();
      // 去重
      Set<String> hashSet = new HashSet<>(list);
      // 查询短信模板
      SmsTemplate smsTemplate = smsTemplateService.getOne(new QueryWrapper<SmsTemplate>().eq("template_id", templateId));
      // 拼接短信标题数组
      String [] titleArr = getSmsTitleArr(smsTemplate);
      // 批量发送短信
      Map<String, Object> batchSendSmsMap = batchSendSms(hashSet, titleArr, param, smsTemplate,errPhones);
      // 返回
      return batchSendSmsMap;
   }
   /**
    * 导入表格发送预警短信
    * @param list 集合数据
    * @param templateId 模板id
    * @param param 通用参数
    * @param content 发送内容
    * @return
    */
   @Override
   public Object importSendSms(List<SendSmsExcel> list,String templateId,String param, String content) {
      // 查询短信模板
      SmsTemplate smsTemplate = smsTemplateService.getOne(new QueryWrapper<SmsTemplate>().eq("template_id", templateId));
      // 判断模板是否为具名变量模板(目前已筛选出都是具名变量模板)
      // 判断模板中是否包含参数,如果无参数,对比是否传参数
      boolean validate = validatorParam(smsTemplate,param);
      if (!validate){
         return R.data(400,"参数个数不对应,请检查后修改导入!",null);
      }
      // 转换
      List<String> stringList = list.stream().map(SendSmsExcel::getPhone).collect(Collectors.toList());
      // 获取水库个数
      List<String> errPhones = new ArrayList<>();
      // 去重
      Set<String> hashSet = new HashSet<>(stringList);
      // 拼接短信标题数组
      String [] titleArr = getSmsTitleArr(smsTemplate);
      // 批量发送不能超过1000 个号码,需分组发送
      List<String> arrayList = new ArrayList<>(hashSet);
      List<List<String>> partition = Lists.partition(arrayList, 1000);
      int i = 0;
      String errMsg = "";
      for (List<String> phoneList : partition) {
         HashSet<String> sets = new HashSet<>(phoneList);
         // 批量发送短信
         Map<String, Object> batchSendSmsMap = batchSendSms(sets, titleArr, param, smsTemplate,errPhones);
         // 取出发送结果
         ComResult<DynSMSSendDataResult> resultComResult = (ComResult<DynSMSSendDataResult>) batchSendSmsMap.get("resultComResult");
         //
         if(!resultComResult.getCode().equals(0)){
            i++;
            errMsg = resultComResult.getMsg();
            break;
         }
      }
      if (i>0){
         // 返回resultComResult
         return R.data(400,"发送失败!" + errMsg,null);
      }
      // 返回resultComResult
      return R.data(200,"发送成功!",null);
   }
   /**
    * 校验参数
    * @param smsTemplate
    * @param param
    */
   private boolean validatorParam(SmsTemplate smsTemplate, String param) {
      int length = 0;
      if (null!= param && !param.equals("")) {
         length = Arrays.asList(param.split(",")).size();
      }
      // 解析模板
      String str = smsTemplate.getContent().replaceAll("\\{.+?\\}", "%s");
      int countChar = countChar(str, '%');
      if (length==countChar){
         return true;
      }else {
         return false;
      }
   }
   /**
    * 计算某个字符在字符串中的个数
    * @param str 字符串
    * @param target 字符
    * @return
    */
   public int countChar(String str, char target) {
      String targetStr = String.valueOf(target);
      String replacedStr = str.replaceAll(targetStr, "");
      return str.length() - replacedStr.length();
   }
}