test(String phone) {
+ return MhSmsClient.getClient().smsSend(VoiceSmsTemplateConst.EXPERT_INVITE, Collections.singletonList(phone));
}
@ApiOperation("短信回复")
@GetMapping("/aplySms")
- public SmsReplyResponse smsReply(String uuid) {
- return smsServiceClient.smsReply(uuid);
+ public SmsReplyDTO smsReply(String uuid) {
+ return MhSmsClient.getClient().smsReply(uuid);
}
@ApiOperation("短信回执")
@GetMapping("/status")
public SmsReceipt smsReceipt(String uuid) {
- return smsServiceClient.smsReceipt(uuid);
+ return MhSmsClient.getClient().smsReceipt(uuid);
}
@ApiOperation("会议日历")
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/MeetingExpert.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/MeetingExpert.java
index 0ca760b..3088f10 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/MeetingExpert.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/MeetingExpert.java
@@ -26,6 +26,7 @@ public class MeetingExpert implements Serializable {
@Tolerate
public MeetingExpert() {
+ // 默认无参构造
}
private static final long serialVersionUID = 1L;
@@ -61,11 +62,9 @@ public class MeetingExpert implements Serializable {
@ApiModelProperty("是否已确认名单")
private Boolean confirmedRoster;
+ @ApiModelProperty("提交标识")
private String submitKey;
- @ApiModelProperty("短信发送返回的uuid")
- private String smsUuid;
-
@ApiModelProperty("通知方式:1电话 2短信")
private String notifyWay;
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingCallOrMsgHelper.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingNotifyHelper.java
similarity index 74%
rename from hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingCallOrMsgHelper.java
rename to hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingNotifyHelper.java
index 5c4ed30..221fad8 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingCallOrMsgHelper.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/MeetingNotifyHelper.java
@@ -3,37 +3,34 @@ package com.hz.pm.api.meeting.helper;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.hz.pm.api.common.helper.MsgCallHelper;
import com.hz.pm.api.meeting.constant.MeetingMsgTemplateConst;
import com.hz.pm.api.meeting.entity.domain.Meeting;
import com.hz.pm.api.meeting.entity.domain.MeetingExpert;
import com.hz.pm.api.meeting.entity.enumeration.ExpertInviteTypeEnum;
import com.hz.pm.api.meeting.entity.enumeration.ExpertNotifyTypeEnum;
import com.hz.pm.api.meeting.entity.enumeration.MeetingReviewTypeEnum;
-import com.hz.pm.api.meeting.task.ExpertCallResultRewriteTask;
import com.hz.pm.api.organization.model.entity.DingEmployeeInfo;
import com.hz.pm.api.organization.model.entity.DingOrganization;
import com.hz.pm.api.organization.service.IDingEmployeeInfoService;
import com.hz.pm.api.organization.service.IDingOrganizationService;
+import com.hz.pm.api.sms.constant.VoiceSmsTemplateConst;
import com.hz.pm.api.sms.utils.DateUtil;
import com.hz.pm.api.staging.enums.MsgTypeEnum;
import com.hz.pm.api.staging.service.INdWorkNoticeStagingService;
import com.hz.pm.api.sys.model.entity.Notify;
+import com.hz.pm.api.sys.model.enumeration.BizTypeEnum;
import com.hz.pm.api.sys.service.INotifyService;
import com.hz.pm.api.todocenter.bean.entity.WorkNoticeInfo;
import com.hz.pm.api.user.model.entity.UserInfo;
import com.hz.pm.api.user.service.IUserInfoService;
import com.ningdatech.basic.util.CollUtils;
-import com.ningdatech.yxt.model.cmd.SendSmsCmd.SendSmsContext;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
+import java.util.*;
/**
*
@@ -45,15 +42,14 @@ import java.util.stream.Collectors;
**/
@Component
@AllArgsConstructor
-public class MeetingCallOrMsgHelper {
+public class MeetingNotifyHelper {
private final IUserInfoService userInfoService;
- private final YxtClientHelper yxtClientHelper;
+ private final MsgCallHelper msgCallHelper;
private final INdWorkNoticeStagingService workNoticeStagingService;
private final IDingEmployeeInfoService dingEmployeeInfoService;
private final IDingOrganizationService dingOrganizationService;
private final INotifyService notifyService;
- private final ExpertCallResultRewriteTask expertCallResultRewriteTask;
private static String officialTime(LocalDateTime time) {
return time.format(DateUtil.DTF_YMD_HM);
@@ -100,10 +96,7 @@ public class MeetingCallOrMsgHelper {
UserInfo info = userInfoService.getById(userId);
String msgContent = String.format(MeetingMsgTemplateConst.INVITE_END, meetingName);
// 音信通消息
- SendSmsContext yxtContent = new SendSmsContext();
- yxtContent.setContent(msgContent);
- yxtContent.setReceiveNumber(info.getMobile());
- yxtClientHelper.sendSms(yxtContent);
+ msgCallHelper.sendMsg(info.getMobile(), msgContent, BizTypeEnum.EXPERT_INVITE_STOP);
// 发送工作通知
if (info.getAccountId() != null) {
WorkNoticeInfo swn = getSendWorkNoticeInfo(info.getAccountId());
@@ -124,7 +117,6 @@ public class MeetingCallOrMsgHelper {
String sTime = officialTime(meeting.getStartTime());
String eTime = officialTime(meeting.getEndTime());
String meetingTime = sTime + "至" + eTime;
- List yxtContents = new ArrayList<>();
List notifies = new ArrayList<>();
List workingNotices = new ArrayList<>();
experts.forEach(w -> {
@@ -132,10 +124,7 @@ public class MeetingCallOrMsgHelper {
w.getExpertName(), officialTime(w.getCreateOn()), meetingTime, meeting.getMeetingAddress(),
meeting.getConnecter(), meeting.getContact());
// 音信通消息
- SendSmsContext yxtContent = new SendSmsContext();
- yxtContent.setContent(msgContent);
- yxtContent.setReceiveNumber(w.getMobile());
- yxtContents.add(yxtContent);
+ msgCallHelper.sendMsg(w.getMobile(), msgContent, BizTypeEnum.MEETING_ROSTER_CONFIRM);
UserInfo info = userMap.get(w.getExpertId());
// 发送工作通知
if (info.getAccountId() != null) {
@@ -149,7 +138,6 @@ public class MeetingCallOrMsgHelper {
}
});
notifyService.saveBatch(notifies);
- yxtClientHelper.sendSms(yxtContents);
workNoticeStagingService.addByWorkNotice(workingNotices, MsgTypeEnum.EXPERT_REVIEW);
}
@@ -157,15 +145,11 @@ public class MeetingCallOrMsgHelper {
public void sendCancelMeetingMsg(List experts, Meeting meeting) {
String startTime = officialTime(meeting.getStartTime());
String meetingType = MeetingReviewTypeEnum.getValue(meeting.getType());
- List contexts = experts.stream().map(w -> {
+ for (MeetingExpert expert : experts) {
String content = String.format(MeetingMsgTemplateConst.MEETING_CANCEL,
- w.getExpertName(), startTime, meetingType, meeting.getContact());
- SendSmsContext context = new SendSmsContext();
- context.setReceiveNumber(w.getMobile());
- context.setContent(content);
- return context;
- }).collect(Collectors.toList());
- yxtClientHelper.sendSms(contexts);
+ expert.getExpertName(), startTime, meetingType, meeting.getContact());
+ msgCallHelper.sendMsg(expert.getMobile(), content, BizTypeEnum.MEETING_CANCEL);
+ }
}
/**
@@ -175,27 +159,36 @@ public class MeetingCallOrMsgHelper {
* @param experts 待通知专家
* @author WendyYang
**/
-// public void callExpertByMeeting(Meeting meeting, List experts) {
-// String voiceContent = String.format(VoiceSmsTemplateConst.EXPERT_INVITE,
-// meeting.getHoldOrg(), meeting.getName(), officialTime(meeting.getStartTime()),
-// meeting.getMeetingAddress());
-// List callContexts = CollUtils.convert(experts, w -> {
-// SubmitTaskCallContext context = new SubmitTaskCallContext();
-// context.setContent(voiceContent);
-// context.setReceiveNumber(w.getMobile());
-// return context;
-// });
-// String submitKey = yxtClientHelper.submitCallTask(callContexts);
-// experts.forEach(w -> w.setSubmitKey(submitKey));
-// }
-
- public void smsOrCallExpertByMeeting(Meeting meeting, List experts) {
- if(ExpertNotifyTypeEnum.CALL.eq(meeting.getNotifyWay())){
- // todo 电话通知
- }else if(ExpertNotifyTypeEnum.SMS.eq(meeting.getNotifyWay())){
- // 短信通知
- String smsUuid = expertCallResultRewriteTask.sendExpertSms(experts, meeting);
- experts.forEach(w -> w.setSmsUuid(smsUuid));
+ private void callExperts(Meeting meeting, List experts) {
+ String content = String.format(VoiceSmsTemplateConst.EXPERT_INVITE,
+ meeting.getHoldOrg(), meeting.getName(), officialTime(meeting.getStartTime()),
+ meeting.getMeetingAddress());
+ Set phones = CollUtils.fieldSet(experts, MeetingExpert::getMobile);
+ String submitKey = msgCallHelper.sendCall(phones, content, BizTypeEnum.EXPERT_INVITE);
+ experts.forEach(w -> w.setSubmitKey(submitKey));
+ }
+
+ /**
+ * 发送专家短信任务
+ *
+ * @param experts 专家
+ * @param meeting 会议
+ */
+ private void smsExperts(Meeting meeting, List experts) {
+ String content = String.format(VoiceSmsTemplateConst.EXPERT_INVITE,
+ meeting.getHoldOrg(), meeting.getName(), officialTime(meeting.getStartTime()),
+ meeting.getMeetingAddress());
+ Set phones = CollUtils.fieldSet(experts, MeetingExpert::getMobile);
+ String submitKey = msgCallHelper.sendMsg(phones, content, BizTypeEnum.EXPERT_INVITE);
+ // 短信发送成功返回的UUID
+ experts.forEach(w -> w.setSubmitKey(submitKey));
+ }
+
+ public void notifyExperts(Meeting meeting, List experts) {
+ if (ExpertNotifyTypeEnum.CALL.eq(meeting.getNotifyWay())) {
+ callExperts(meeting, experts);
+ } else if (ExpertNotifyTypeEnum.SMS.eq(meeting.getNotifyWay())) {
+ smsExperts(meeting, experts);
}
}
@@ -209,10 +202,7 @@ public class MeetingCallOrMsgHelper {
msgContent = String.format(MeetingMsgTemplateConst.EXPERT_LEAVE_APPOINT, meeting.getName(), expert.getExpertName());
}
UserInfo info = userInfoService.getById(userId);
- SendSmsContext yxtContent = new SendSmsContext();
- yxtContent.setContent(msgContent);
- yxtContent.setReceiveNumber(info.getMobile());
- yxtClientHelper.sendSms(yxtContent);
+ msgCallHelper.sendMsg(info.getMobile(), msgContent, BizTypeEnum.EXPERT_LEAVE);
// 发送工作通知
if (info.getAccountId() != null) {
WorkNoticeInfo swn = getSendWorkNoticeInfo(info.getAccountId());
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/SmsOrCallClient.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/SmsOrCallClient.java
deleted file mode 100644
index a257551..0000000
--- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/SmsOrCallClient.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.hz.pm.api.meeting.helper;
-
-import com.alibaba.fastjson.JSONObject;
-import com.hz.pm.api.external.sms.SmsServiceClient;
-import com.hz.pm.api.external.sms.dto.SmsDTO;
-import com.hz.pm.api.external.sms.vo.SmsSendResponse;
-import com.hz.pm.api.meeting.entity.domain.MeetingExpertSms;
-import com.hz.pm.api.meeting.mapper.MeetingExpertSmsMapper;
-import com.ningdatech.yxt.model.cmd.SendSmsCmd;
-import com.ningdatech.yxt.model.cmd.SubmitTaskCallCmd;
-import com.ningdatech.yxt.model.cmd.SubmitTaskCallResponse;
-import com.ningdatech.yxt.model.response.SendSmsResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Component;
-
-import java.time.LocalDateTime;
-import java.util.Arrays;
-
-/**
- * @author wangrenkang
- * @date 2024-02-22 16:39:35
- */
-@Component
-@AllArgsConstructor
-@Primary
-public class SmsOrCallClient implements com.ningdatech.yxt.client.YxtClient {
-
- private final SmsServiceClient smsServiceClient;
- private final MeetingExpertSmsMapper meetingExpertSmsMapper;
-
- /**
- * 发送短信
- * @param sendSmsCmd 短信内容,短信手机号
- * @return
- */
- @Override
- public SendSmsResponse submitSmsTask(SendSmsCmd sendSmsCmd) {
- sendSmsCmd.getContextList().forEach(sms ->{
- SmsDTO smsSendResponseSmsDto = smsServiceClient.smsSend(sms.getContent(), Arrays.asList(sms.getReceiveNumber()));
- String resultUuid = smsSendResponseSmsDto.getData().getResult();
- // 保存短信发送记录
- MeetingExpertSms meetingExpertSms = MeetingExpertSms.builder()
- .createOn(LocalDateTime.now())
- .smsUuid(resultUuid)
- .content(sms.getContent())
- .phones(sms.getReceiveNumber())
- .smsResult(smsSendResponseSmsDto.toString())
- .build();
- meetingExpertSmsMapper.insert(meetingExpertSms);
- });
- return null;
- }
-
- @Override
- public SubmitTaskCallResponse submitTaskCall(SubmitTaskCallCmd submitTaskCallCmd) {
- return null;
- }
-
- @Override
- public JSONObject getSentResultSms(String transactionId) {
- return null;
- }
-
- @Override
- public JSONObject getSentResultCall(String transactionId) {
- return null;
- }
-}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/YxtClientHelper.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/YxtClientHelper.java
deleted file mode 100644
index 4d8d163..0000000
--- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/helper/YxtClientHelper.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.hz.pm.api.meeting.helper;
-
-import com.ningdatech.yxt.client.YxtClient;
-import com.ningdatech.yxt.model.cmd.SendSmsCmd;
-import com.ningdatech.yxt.model.cmd.SendSmsCmd.SendSmsContext;
-import com.ningdatech.yxt.model.cmd.SubmitTaskCallResponse;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Component;
-
-import java.util.Collections;
-import java.util.List;
-
-import static com.ningdatech.yxt.model.cmd.SubmitTaskCallCmd.SubmitTaskCallContext;
-import static com.ningdatech.yxt.model.cmd.SubmitTaskCallCmd.of;
-
-/**
- *
- * YxtCallOrSmsHelper
- *
- *
- * @author WendyYang
- * @since 23:59 2022/8/31
- */
-@Component
-@AllArgsConstructor
-public class YxtClientHelper {
-
- private final YxtClient yxtClient;
-
- public String submitCallTask(List callContexts) {
- SubmitTaskCallResponse callResponse = yxtClient.submitTaskCall(of(callContexts));
- return callResponse.getSubmitKey();
- }
-
- public void sendSms(List smsList) {
- SendSmsCmd cmd = new SendSmsCmd();
- cmd.setContextList(smsList);
-// cmd.setSmsSignEnum(YxtSmsSignEnum.LS_BIG_DATA_BUREAU);
- yxtClient.submitSmsTask(cmd);
- }
-
- public void sendSms(SendSmsContext sms) {
- sendSms(Collections.singletonList(sms));
- }
-
-}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/ExpertInviteManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/ExpertInviteManage.java
index 73ed55a..d5514ff 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/ExpertInviteManage.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/ExpertInviteManage.java
@@ -20,7 +20,7 @@ import com.hz.pm.api.meeting.entity.enumeration.AvoidTypeEnum;
import com.hz.pm.api.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.hz.pm.api.meeting.entity.enumeration.MeetingStatusEnum;
import com.hz.pm.api.meeting.helper.ExpertInviteHelper;
-import com.hz.pm.api.meeting.helper.MeetingCallOrMsgHelper;
+import com.hz.pm.api.meeting.helper.MeetingNotifyHelper;
import com.hz.pm.api.meeting.service.IExpertInviteRuleService;
import com.hz.pm.api.meeting.service.IMeetingExpertService;
import com.hz.pm.api.meeting.service.IMeetingService;
@@ -68,7 +68,7 @@ public class ExpertInviteManage {
private final IExpertUserFullInfoService expertUserFullInfoService;
private final IMeetingService meetingService;
private final IExpertAvoidCompanyService expertAvoidCompanyService;
- private final MeetingCallOrMsgHelper meetingCallOrMsgHelper;
+ private final MeetingNotifyHelper meetingNotifyHelper;
private final IExpertGovBusinessStripService expertGovBusinessStripService;
@Value("#{randomInviteProperties.recentMeetingCount}")
@@ -576,9 +576,7 @@ public class ExpertInviteManage {
expertInserts.add(expert);
});
}
-// meetingCallOrMsgHelper.callExpertByMeeting(meeting, expertInserts);
- // 短信或电话提醒
- meetingCallOrMsgHelper.smsOrCallExpertByMeeting(meeting, expertInserts);
+ meetingNotifyHelper.notifyExperts(meeting, expertInserts);
}
meetingExpertService.saveBatch(expertInserts);
}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/MeetingManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/MeetingManage.java
index 02cbe3f..bff0f4e 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/MeetingManage.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/manage/MeetingManage.java
@@ -29,7 +29,7 @@ import com.hz.pm.api.meeting.entity.enumeration.MeetingStatusEnum;
import com.hz.pm.api.meeting.entity.req.*;
import com.hz.pm.api.meeting.entity.vo.*;
import com.hz.pm.api.meeting.helper.ExpertInviteHelper;
-import com.hz.pm.api.meeting.helper.MeetingCallOrMsgHelper;
+import com.hz.pm.api.meeting.helper.MeetingNotifyHelper;
import com.hz.pm.api.meeting.helper.MeetingManageHelper;
import com.hz.pm.api.meeting.service.*;
import com.hz.pm.api.meeting.task.ExpertRandomInviteTask;
@@ -91,7 +91,7 @@ public class MeetingManage {
private final IBelongOrgService belongOrgService;
private final IDingOrganizationService dingOrganizationService;
private final ExpertInviteHelper expertInviteHelper;
- private final MeetingCallOrMsgHelper meetingCallOrMsgHelper;
+ private final MeetingNotifyHelper meetingNotifyHelper;
private final IMeetingExpertJudgeService expertJudgeService;
private final IMeetingExpertJudgeService meetingExpertJudgeService;
@@ -686,7 +686,7 @@ public class MeetingManage {
// 发送通知给专家
List experts = meetingExpertService.listAgreedExperts(meetingId);
if (!experts.isEmpty()) {
- meetingCallOrMsgHelper.sendCancelMeetingMsg(experts, meeting);
+ meetingNotifyHelper.sendCancelMeetingMsg(experts, meeting);
}
} finally {
distributedLock.releaseLock(key);
@@ -846,7 +846,7 @@ public class MeetingManage {
.in(MeetingExpert::getId, currConfirmedMeIds)
.set(MeetingExpert::getConfirmedRoster, Boolean.TRUE);
meetingExpertService.update(meUpdate);
- meetingCallOrMsgHelper.sendConfirmedRosterMsg(expertNoticing, meeting);
+ meetingNotifyHelper.sendConfirmedRosterMsg(expertNoticing, meeting);
} finally {
distributedLock.releaseLock(key);
}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/ExpertCallResultRewriteTask.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/ExpertCallResultRewriteTask.java
index 35afce0..cd9dbd1 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/ExpertCallResultRewriteTask.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/ExpertCallResultRewriteTask.java
@@ -1,47 +1,33 @@
package com.hz.pm.api.meeting.task;
-import cn.hutool.core.util.ObjectUtil;
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.hz.pm.api.common.util.StrUtils;
-import com.hz.pm.api.external.sms.SmsServiceClient;
-import com.hz.pm.api.external.sms.dto.SmsDTO;
-import com.hz.pm.api.external.sms.vo.SmsReply;
-import com.hz.pm.api.external.sms.vo.SmsReplyResponse;
-import com.hz.pm.api.external.sms.vo.SmsSendResponse;
+import com.hz.pm.api.common.util.ThreadPoolUtil;
import com.hz.pm.api.meeting.entity.domain.ExpertInviteRule;
-import com.hz.pm.api.meeting.entity.domain.Meeting;
import com.hz.pm.api.meeting.entity.domain.MeetingExpert;
-import com.hz.pm.api.meeting.entity.domain.MeetingExpertSms;
import com.hz.pm.api.meeting.entity.dto.RandomInviteRuleDTO;
-import com.hz.pm.api.meeting.entity.dto.SmsReplyDetails;
-import com.hz.pm.api.meeting.entity.dto.YxtCallBackDTO;
import com.hz.pm.api.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.hz.pm.api.meeting.entity.enumeration.ExpertInviteTypeEnum;
-import com.hz.pm.api.meeting.mapper.MeetingExpertSmsMapper;
import com.hz.pm.api.meeting.service.IExpertInviteRuleService;
import com.hz.pm.api.meeting.service.IMeetingExpertService;
-import com.hz.pm.api.sms.constant.VoiceSmsTemplateConst;
-import com.ningdatech.basic.util.StrPool;
-import com.ningdatech.yxt.entity.SysMsgRecordDetail;
-import com.ningdatech.yxt.service.ISysMsgRecordDetailService;
+import com.hz.pm.api.sys.model.entity.MsgCallRecord;
+import com.hz.pm.api.sys.model.entity.MsgCallRecord.ReplyStatus;
+import com.hz.pm.api.sys.service.IMsgCallRecordService;
+import com.ningdatech.basic.util.CollUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
-import java.util.stream.Collectors;
-import static com.hz.pm.api.meeting.entity.enumeration.ExpertAttendStatusEnum.*;
+import static com.hz.pm.api.meeting.entity.enumeration.ExpertAttendStatusEnum.NOTICING;
/**
*
@@ -58,321 +44,114 @@ import static com.hz.pm.api.meeting.entity.enumeration.ExpertAttendStatusEnum.*;
@AllArgsConstructor
public class ExpertCallResultRewriteTask {
- private final RandomInviteProperties randomInviteProperties;
-
- private final ThreadPoolTaskScheduler scheduler;
+ private final RandomInviteProperties properties;
private final IMeetingExpertService meetingExpertService;
private final IExpertInviteRuleService inviteRuleService;
- private final ISysMsgRecordDetailService msgRecordDetailService;
- private final SmsServiceClient smsServiceClient;
- private final MeetingExpertSmsMapper meetingExpertSmsMapper;
+ private final IMsgCallRecordService msgCallRecordService;
- private final static int MINUTES_CALL_RESULT_FEEDBACK = 15;
+ private static final int OVERTIME = 30;
private static final String AGREE_KEY = "1";
+ private static final String REFUSE_KEY = "2";
@PostConstruct
public void initTask() {
- if (!randomInviteProperties.getEnable()) {
+ if (Boolean.FALSE.equals(properties.getEnable())) {
log.warn("随机邀请已关闭……");
return;
}
// 处理电话结果回填
- Instant startTime = Instant.now().plus(randomInviteProperties.getResultRewriteFixedRate(), ChronoUnit.MINUTES);
- Duration fixedRate = Duration.ofMinutes(randomInviteProperties.getResultRewriteFixedRate());
-// scheduler.scheduleAtFixedRate(this::rewritePhoneCallResult, startTime, fixedRate);
-
+ Instant startTime = Instant.now().plus(properties.getResultRewriteFixedRate(), ChronoUnit.MINUTES);
+ Duration fixedRate = Duration.ofMinutes(properties.getResultRewriteFixedRate());
// 处理短信结果回填
- Instant smsStartTime = Instant.now().plus(randomInviteProperties.getResultRewriteFixedRate(), ChronoUnit.MINUTES);
- scheduler.scheduleAtFixedRate(this::expertSmsReply, smsStartTime, fixedRate);
+ ThreadPoolUtil.SCHEDULER.scheduleAtFixedRate(this::expertReplyRewrite, startTime, fixedRate);
}
- public void expertSmsReply() {
- log.info("开始执行短信回复查询任务:{}", Thread.currentThread().getName());
+ private void expertReplyRewrite() {
+ log.info("开始执行短信回复查询任务");
// 查询所有邀请的专家信息 状态为通话中的
- LambdaQueryWrapper meQuery = Wrappers.lambdaQuery(MeetingExpert.class)
+ Wrapper meQuery = Wrappers.lambdaQuery(MeetingExpert.class)
.eq(MeetingExpert::getStatus, NOTICING.getCode())
+ .isNotNull(MeetingExpert::getSubmitKey)
.eq(MeetingExpert::getInviteType, ExpertInviteTypeEnum.RANDOM.getCode());
List experts = meetingExpertService.list(meQuery);
if (experts.isEmpty()) {
log.info("暂无短信回复任务执行");
return;
}
- // 所有随机邀请的短信Uuid
- List smsUuids = experts.stream()
- .map(expert -> expert.getSmsUuid())
- .filter(uuid -> uuid != null)
- .distinct()
- .collect(Collectors.toList());
- Set randomRuleIds = experts.stream()
- .map(MeetingExpert::getRuleId).collect(Collectors.toSet());
+ List submitKeys = CollUtils.fieldList(experts, MeetingExpert::getSubmitKey);
+ List mobiles = CollUtils.fieldList(experts, MeetingExpert::getMobile);
+ Set ruleIds = CollUtils.fieldSet(experts, MeetingExpert::getRuleId);
// 查询随机邀请回调等待时间
- Map callbackMinutes = new HashMap<>(randomRuleIds.size());
- if (!randomRuleIds.isEmpty()) {
- List inviteRules = inviteRuleService.listByIds(randomRuleIds);
- inviteRules.forEach(expert -> {
- RandomInviteRuleDTO rule = JSONObject.parseObject(expert.getInviteRule(), RandomInviteRuleDTO.class);
- callbackMinutes.put(expert.getId(), rule.getWaitForCallbackMinutes());
- });
+ Map callbackMinutes = new HashMap<>(ruleIds.size());
+ List rules = inviteRuleService.listByIds(ruleIds);
+ for (ExpertInviteRule rule : rules) {
+ RandomInviteRuleDTO ruleDetail = JSONUtil.toBean(rule.getInviteRule(), RandomInviteRuleDTO.class);
+ callbackMinutes.put(rule.getId(), ruleDetail.getWaitForCallbackMinutes());
}
-
- // 获取专家回复内容
- SmsReplyDetails smsReplyDetails = viewSmsReplies(smsUuids);
-
- List updates = new ArrayList<>();
-
+ // 查询短信语音回执结果
+ Wrapper mcrQuery = Wrappers.lambdaQuery(MsgCallRecord.class)
+ .in(MsgCallRecord::getSubmitKey, submitKeys)
+ .in(MsgCallRecord::getReceivePhone, mobiles)
+ .isNotNull(MsgCallRecord::getReplyOn);
+ List records = msgCallRecordService.list(mcrQuery);
+ Map replayMap = CollUtils.listToMap(records,
+ w -> w.getSubmitKey() + "#" + w.getReceivePhone());
+
+ List changes = new ArrayList<>();
for (MeetingExpert expert : experts) {
-
- Integer minutes = ObjectUtil.defaultIfNull(callbackMinutes.get(expert.getRuleId()), MINUTES_CALL_RESULT_FEEDBACK);
- // 判断回复状态
- Optional status = getStatusByMsgRecordDetail(smsReplyDetails, minutes, expert);
- if (status.isPresent()) {
- MeetingExpert update = new MeetingExpert();
- update.setUpdateBy(0L);
- update.setUpdateOn(LocalDateTime.now());
- update.setId(expert.getId());
- update.setStatus(status.get());
- updates.add(update);
- }
- }
- meetingExpertService.updateBatchById(updates);
- }
-
-
- public void rewritePhoneCallResult() {
- log.info("开始执行电话结果回填任务:{}", Thread.currentThread().getName());
- // 查询所有邀请的专家信息 状态为通话中的
- LambdaQueryWrapper meQuery = Wrappers.lambdaQuery(MeetingExpert.class)
- .eq(MeetingExpert::getStatus, NOTICING.getCode())
- .eq(MeetingExpert::getInviteType, ExpertInviteTypeEnum.RANDOM.getCode());
- List experts = meetingExpertService.list(meQuery);
- if (experts.isEmpty()) {
- log.info("暂无电话结果回填任务执行");
- return;
- }
- // 所有随机邀请的规则ID
- Map submitKeys = new HashMap<>(experts.size());
- Set randomRuleIds = experts.stream().peek(w -> submitKeys.put(w.getId(), w.getSubmitKey()))
- .map(MeetingExpert::getRuleId).collect(Collectors.toSet());
- // 查询随机邀请回调等待时间
- Map callbackMinutes = new HashMap<>(randomRuleIds.size());
- if (!randomRuleIds.isEmpty()) {
- List inviteRules = inviteRuleService.listByIds(randomRuleIds);
- inviteRules.forEach(w -> {
- RandomInviteRuleDTO rule = JSONObject.parseObject(w.getInviteRule(), RandomInviteRuleDTO.class);
- callbackMinutes.put(w.getId(), rule.getWaitForCallbackMinutes());
+ String submitKeyMobile = expert.getSubmitKey() + "#" + expert.getMobile();
+ Integer overtime = callbackMinutes.getOrDefault(expert.getRuleId(), OVERTIME);
+ MsgCallRecord mcr = replayMap.get(submitKeyMobile);
+ buildStatus(mcr, overtime, expert).ifPresent(w -> {
+ expert.setStatus(w.getCode());
+ changes.add(expert);
});
}
- LambdaQueryWrapper msgRecordDetailQuery = Wrappers.lambdaQuery(SysMsgRecordDetail.class)
- .in(SysMsgRecordDetail::getSubmitKey, submitKeys.values());
- List recordDetailList = msgRecordDetailService.list(msgRecordDetailQuery);
- if (recordDetailList.isEmpty()) {
- return;
- }
- Map recordDetailMap = recordDetailList.stream()
- .collect(Collectors.toMap(w -> w.getSubmitKey() + StrPool.UNDERSCORE + w.getReceiveNumber(), w -> w));
- List updates = new ArrayList<>(), agrees = new ArrayList<>();
- for (MeetingExpert expert : experts) {
- String key = expert.getSubmitKey() + StrPool.UNDERSCORE + expert.getMobile();
- SysMsgRecordDetail msgRecordDetail = recordDetailMap.get(key);
- if (msgRecordDetail == null) {
- // 极端情况下获取不到submitKey异常情况
- continue;
- }
- Integer minutes = ObjectUtil.defaultIfNull(callbackMinutes.get(expert.getRuleId()), MINUTES_CALL_RESULT_FEEDBACK);
- Optional status = getStatusByMsgRecordDetail(msgRecordDetail, minutes, expert.getCreateOn());
- if (status.isPresent()) {
- MeetingExpert update = new MeetingExpert();
- update.setUpdateBy(0L);
- update.setUpdateOn(LocalDateTime.now());
- update.setId(expert.getId());
- update.setStatus(status.get());
- if (AGREED.eq(update.getStatus())) {
- // 发送专家确认参加的短信通知
- // sendAgreeNotice(expert);
- agrees.add(expert);
- }
- updates.add(update);
- }
- }
- meetingExpertService.updateBatchById(updates);
+ meetingExpertService.updateBatchById(changes);
}
- private static Optional getStatusByMsgRecordDetail(SysMsgRecordDetail mrd, int minutes, LocalDateTime createOn) {
- LocalDateTime limitTime = LocalDateTime.now().minusMinutes(minutes);
- String callBackJson = mrd.getCallBackJson();
- boolean waiting = limitTime.isBefore(createOn);
- boolean hasCallBack = StrUtils.isNotBlank(callBackJson);
- if (!hasCallBack && waiting) {
- return Optional.empty();
- }
+ /**
+ * 构建专家状态
+ *
+ * @param mcr 回复记录
+ * @param overtime 超时时间
+ * @param expert 专家
+ * @return 专家状态
+ */
+ private static Optional buildStatus(MsgCallRecord mcr,
+ Integer overtime,
+ MeetingExpert expert) {
+ LocalDateTime now = LocalDateTime.now();
+ boolean isOvertime = expert.getCreateOn().plusMinutes(overtime).isBefore(now);
ExpertAttendStatusEnum status;
- if (hasCallBack) {
- try {
- YxtCallBackDTO callback = JSONObject.parseObject(callBackJson, YxtCallBackDTO.class);
- LocalDateTime dialBeginTime = callback.getDialBeginTime();
- if (dialBeginTime == null) {
- return Optional.empty();
- }
- Integer resultCode = callback.getResultCode();
- if (resultCode != null && resultCode == 0) {
- String pressKey = callback.getPressKey();
- if (pressKey != null) {
- pressKey = pressKey.replaceAll("\\*", "").trim();
- }
- if (StrUtils.isBlank(pressKey) && waiting) {
- return Optional.empty();
- }
- status = AGREE_KEY.equals(pressKey) ? AGREED : REFUSED;
- } else {
- if (waiting) {
- return Optional.empty();
- }
- status = REFUSED;
+ if (mcr != null || isOvertime) {
+ if (isOvertime) {
+ status = ExpertAttendStatusEnum.UNANSWERED;
+ } else {
+ ReplyStatus replyStatus = mcr.getReplyStatus();
+ switch (replyStatus) {
+ case OVERTIME:
+ case FAILED:
+ status = ExpertAttendStatusEnum.UNANSWERED;
+ break;
+ case SUCCESS:
+ String reply = StrUtil.trim(mcr.getReplyContent());
+ if (AGREE_KEY.equals(reply)) {
+ status = ExpertAttendStatusEnum.AGREED;
+ } else {
+ status = ExpertAttendStatusEnum.REFUSED;
+ }
+ break;
+ default:
+ status = null;
+ break;
}
- } catch (Exception e) {
- log.error("获取电话回调结果异常{}", mrd, e);
- status = UNANSWERED;
}
} else {
- // 超时未回复设置为拒绝参加
- status = REFUSED;
+ status = null;
}
- return Optional.of(status.getCode());
+ return Optional.ofNullable(status);
}
- private static Optional getStatusByMsgRecordDetail(SmsReplyDetails smsReplyDetails, int minutes, MeetingExpert expert) {
- Map> accept = smsReplyDetails.getAccept() //回复1同意参加的手机号
- , reject = smsReplyDetails.getReject() //回复2拒绝参加的手机号
- , other = smsReplyDetails.getOther(); //回复其他的专家
- Map> errorPhones = new HashMap<>();//发送失败的专家
- // 专家最长响应时间
- LocalDateTime limitTime = LocalDateTime.now().minusMinutes(minutes);
- // 专家抽取时间
- boolean waiting = limitTime.isBefore(expert.getCreateOn());
- ExpertAttendStatusEnum status = NOTICING;
- boolean hasCallBack = ObjectUtil.isEmpty(smsReplyDetails);
- if (hasCallBack && waiting) {
- return Optional.empty();
- }
-// if (!waiting) {
-// status = REFUSED;
-// }
- List errorPhoneList = errorPhones.get(expert.getSmsUuid());
- if(ObjectUtil.isNotEmpty(errorPhoneList) && errorPhoneList.contains(expert.getMobile())){
- // 未应答
- status = UNANSWERED;
- }
- if(ObjectUtil.isNotEmpty(accept)) {
- List smsRepliesAccept = accept.get(expert.getSmsUuid());
- if (ObjectUtil.isNotEmpty(smsRepliesAccept)) {
- boolean containsReplyMobile = smsRepliesAccept.stream()
- .anyMatch(reply -> reply.getReplyMobile().equals(expert.getMobile()));
- if (containsReplyMobile) {
- SmsReply filteredReplies = smsRepliesAccept.stream()
- .filter(reply -> reply.getReplyMobile().equals(expert.getMobile()))
- .collect(Collectors.toList()).get(0);
- // 回复时间
- Instant instant = Instant.ofEpochMilli(filteredReplies.getReplyReplytime());
- LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
- if (localDateTime.isBefore(expert.getCreateOn().plusMinutes(minutes))) {
- status = AGREED;
- } else {
- status = REFUSED;
- }
- }
- }
- }
- if(ObjectUtil.isNotEmpty(reject)) {
- List smsRepliesReject = reject.get(expert.getSmsUuid());
- if (ObjectUtil.isNotEmpty(smsRepliesReject)) {
- boolean containsReplyMobile = smsRepliesReject.stream()
- .anyMatch(reply -> reply.getReplyMobile().equals(expert.getMobile()));
- if (containsReplyMobile) {
- status = REFUSED;
- }
- }
- }
- if(ObjectUtil.isNotEmpty(other)) {
- List smsRepliesOther = other.get(expert.getSmsUuid());
- if (ObjectUtil.isNotEmpty(smsRepliesOther)) {
- boolean containsReplyMobile = smsRepliesOther.stream()
- .anyMatch(reply -> reply.getReplyMobile().equals(expert.getMobile()));
- if (containsReplyMobile) {
- status = REFUSED;
- }
- }
- }
- return Optional.of(status.getCode());
- }
-
- // 发送短信提醒
- public String sendExpertSms(List expertMeetings, Meeting meeting) {
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
- // 短信内容
- String replacedContent = String.format(VoiceSmsTemplateConst.EXPERT_INVITE,
- meeting.getCreator(), meeting.getName(), meeting.getStartTime().format(formatter) + "至" + meeting.getEndTime().format(formatter), meeting.getMeetingAddress());
-
- List phones = expertMeetings.stream().map(obj -> obj.getMobile()).collect(Collectors.toList());
- SmsDTO smsSendResponseSmsDto = smsServiceClient.smsSend(replacedContent, phones);
- // 短信发送成功返回的UUID
- String resultUuid = smsSendResponseSmsDto.getData().getResult();
- // 保存短信发送记录
- MeetingExpertSms meetingExpertSms = MeetingExpertSms.builder()
- .meetingId(meeting.getId().toString())
- .createOn(LocalDateTime.now())
- .smsUuid(resultUuid)
- .content(replacedContent)
- .phones(phones.stream()
- .collect(Collectors.joining(", ")))
- .smsResult(smsSendResponseSmsDto.toString())
- .build();
- meetingExpertSmsMapper.insert(meetingExpertSms);
- return resultUuid;
- }
-
- // 查看短信回复内容并更改专家回复状态
- public SmsReplyDetails viewSmsReplies(List uuids) {
- Map> accept = new HashMap<>()
- , reject = new HashMap<>()
- , other = new HashMap<>();
- Map> errorPhones = new HashMap<>();
- uuids.forEach(uuid -> {
- SmsReplyResponse response = smsServiceClient.smsReply(uuid);
- List smsReplies = response.getResult();
- // 成功回复的手机信息
- if (ObjectUtil.isNotEmpty(smsReplies)){
- // 只有第一条回复的内容有效
- smsReplies = smsReplies.stream()
- .collect(Collectors.groupingBy(SmsReply::getReplyMobile,
- Collectors.minBy(Comparator.comparing(SmsReply::getReplyReplytime))))
- .values().stream()
- .map(Optional::get)
- .collect(Collectors.toList());
- accept.put(uuid, smsReplies.stream()
- .filter(obj -> ObjectUtil.isNotEmpty(obj))
- .filter(smsReply -> "1".equals(smsReply.getReplyContent()))
- .collect(Collectors.toList()));
- reject.put(uuid, smsReplies.stream()
- .filter(obj -> ObjectUtil.isNotEmpty(obj))
- .filter(smsReply -> "2".equals(smsReply.getReplyContent()))
- .collect(Collectors.toList()));
- other.put(uuid, smsReplies.stream()
- .filter(obj -> ObjectUtil.isNotEmpty(obj))
- .filter(smsReply -> !("1".equals(smsReply.getReplyContent()) || "2".equals(smsReply.getReplyContent())))
- .collect(Collectors.toList()));
- }
- // 发送失败的手机号
- if (StrUtils.isNotBlank(response.getErrorPhone())){
- errorPhones.put(uuid, Arrays.asList(response.getErrorPhone().split(",")));
- }
- });
-
- SmsReplyDetails smsReplyDetails = SmsReplyDetails.builder()
- .accept(accept)
- .reject(reject)
- .errorPhones(errorPhones).build();
-
- return smsReplyDetails;
- }
}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/ExpertRandomInviteTask.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/ExpertRandomInviteTask.java
index f7a3293..f674ea0 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/ExpertRandomInviteTask.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/ExpertRandomInviteTask.java
@@ -14,7 +14,7 @@ import com.hz.pm.api.meeting.entity.dto.InviteCacheDTO;
import com.hz.pm.api.meeting.entity.dto.RandomInviteRuleDTO;
import com.hz.pm.api.meeting.entity.enumeration.ExpertAttendStatusEnum;
import com.hz.pm.api.meeting.entity.req.ConfirmedRosterReq;
-import com.hz.pm.api.meeting.helper.MeetingCallOrMsgHelper;
+import com.hz.pm.api.meeting.helper.MeetingNotifyHelper;
import com.hz.pm.api.meeting.manage.ExpertInviteManage;
import com.hz.pm.api.meeting.manage.MeetingManage;
import com.hz.pm.api.meeting.service.IExpertInviteAvoidRuleService;
@@ -72,7 +72,7 @@ public class ExpertRandomInviteTask {
private final IMeetingService meetingService;
private final ExpertInviteManage expertInviteManage;
private final IExpertInviteAvoidRuleService inviteAvoidRuleService;
- private final MeetingCallOrMsgHelper meetingCallOrMsgHelper;
+ private final MeetingNotifyHelper meetingNotifyHelper;
/**
* 用来存入线程执行句柄, 停止定时任务时使用
@@ -227,7 +227,7 @@ public class ExpertRandomInviteTask {
public void invite(Long meetingId, Boolean reInvite, LocalDateTime tsTime) {
log.info("开始进行专家后台抽取:{}", meetingId);
if (!inInviteTimeRange()) {
- log.warn("不在会议抽取执行时间:{}",meetingId);
+ log.warn("不在会议抽取执行时间:{}", meetingId);
return;
}
Meeting meeting = meetingService.getById(meetingId);
@@ -268,9 +268,8 @@ public class ExpertRandomInviteTask {
expert.setStatus(ExpertAttendStatusEnum.NOTICING.getCode());
return expert;
});
-// meetingCallOrMsgHelper.callExpertByMeeting(meeting, expertMeetings);
// 短信或电话提醒
- meetingCallOrMsgHelper.smsOrCallExpertByMeeting(meeting, expertMeetings);
+ meetingNotifyHelper.notifyExperts(meeting, expertMeetings);
log.info("会议:{} 后台抽取专家:{}名", meetingId, expertMeetings.size());
meetingExpertService.saveBatch(expertMeetings);
} else {
@@ -283,7 +282,7 @@ public class ExpertRandomInviteTask {
meetingService.stopRandomInvite(meetingId);
if (notIgnoreCnt.get() == notSupportCnt.get() && notIgnoreCnt.get() > 0) {
// 当未完成抽取且无专家可抽取时
- meetingCallOrMsgHelper.sendInviteStopMsg(meeting.getCreateBy(), meetingId, meeting.getName());
+ meetingNotifyHelper.sendInviteStopMsg(meeting.getCreateBy(), meetingId, meeting.getName());
}
}
// 所有抽取规则抽取人数满足 自动召开会议
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/MsgCallReplyRewriteTask.java b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/MsgCallReplyRewriteTask.java
new file mode 100644
index 0000000..d816b1c
--- /dev/null
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/meeting/task/MsgCallReplyRewriteTask.java
@@ -0,0 +1,171 @@
+package com.hz.pm.api.meeting.task;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.hz.pm.api.common.helper.MsgCallHelper;
+import com.hz.pm.api.common.util.BizUtils;
+import com.hz.pm.api.common.util.MDCThreadPoolTaskExecutor;
+import com.hz.pm.api.external.sms.vo.SmsReply;
+import com.hz.pm.api.external.sms.vo.SmsReplyDTO;
+import com.hz.pm.api.sys.model.entity.MsgCallRecord;
+import com.hz.pm.api.sys.model.entity.MsgCallRecord.ReplyStatus;
+import com.hz.pm.api.sys.model.entity.MsgCallRecord.SendStatus;
+import com.hz.pm.api.sys.model.enumeration.SubmitTypeEnum;
+import com.hz.pm.api.sys.service.IMsgCallRecordService;
+import com.ningdatech.basic.util.CollUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Component;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import static com.hz.pm.api.external.MobileCallClient.ReplyCallDTO;
+
+/**
+ *
+ * MsgCallReplyRewriteTask
+ *
+ *
+ * @author WendyYang
+ * @since 21:29 2024/4/25
+ */
+@Slf4j
+@Component
+public class MsgCallReplyRewriteTask {
+
+ private static final ThreadPoolTaskExecutor EXECUTOR;
+
+ static {
+ // 初始化线程池
+ EXECUTOR = new MDCThreadPoolTaskExecutor();
+ EXECUTOR.setCorePoolSize(2);
+ EXECUTOR.setMaxPoolSize(4);
+ EXECUTOR.setQueueCapacity(100);
+ EXECUTOR.setKeepAliveSeconds(120);
+ EXECUTOR.setThreadPriority(Thread.NORM_PRIORITY);
+ EXECUTOR.setWaitForTasksToCompleteOnShutdown(true);
+ EXECUTOR.setThreadNamePrefix("callRewriteExecutor-");
+ EXECUTOR.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ }
+
+ private final IMsgCallRecordService msgCallRecordService;
+ private final MsgCallHelper msgCallHelper;
+
+ public MsgCallReplyRewriteTask(IMsgCallRecordService msgCallRecordService, MsgCallHelper msgCallHelper) {
+ this.msgCallRecordService = msgCallRecordService;
+ this.msgCallHelper = msgCallHelper;
+ EXECUTOR.initialize();
+ }
+
+
+ @Scheduled(fixedRateString = "${msg-call-reply-write.fixed-rate:2}", timeUnit = TimeUnit.MINUTES)
+ public void replyRewrite() {
+ log.info("开始获取短信电话回执");
+ Wrapper query = Wrappers.lambdaQuery(MsgCallRecord.class)
+ .eq(MsgCallRecord::getNeedReply, Boolean.TRUE)
+ .eq(MsgCallRecord::getSendStatus, SendStatus.SUCCESS)
+ .eq(MsgCallRecord::getReplyStatus, ReplyStatus.WAITING)
+ .isNull(MsgCallRecord::getReplyOn);
+ List records = msgCallRecordService.list(query);
+ if (records.isEmpty()) {
+ return;
+ }
+ LocalDateTime startTime = LocalDateTime.now().minusMinutes(60);
+ Map> map = CollUtils.group(records, w -> w.getCreateOn().isBefore(startTime));
+ List overtimeRecords = map.get(Boolean.TRUE);
+ if (CollUtil.isNotEmpty(overtimeRecords)) {
+ overtimeRecords.forEach(w -> {
+ w.setReplyStatus(ReplyStatus.OVERTIME);
+ w.setReplyOn(LocalDateTime.now());
+ });
+ msgCallRecordService.updateBatchById(overtimeRecords);
+ }
+ List waitingRecords = map.get(Boolean.FALSE);
+ if (CollUtil.isNotEmpty(waitingRecords)) {
+ CollUtils.group(waitingRecords, MsgCallRecord::getSubmitType)
+ .forEach((submitType, recordsBySummitType) -> {
+ if (SubmitTypeEnum.CALL.equals(submitType)) {
+ rewriteCallReply(recordsBySummitType);
+ } else if (SubmitTypeEnum.SMS.equals(submitType)) {
+ rewriteSmsReply(recordsBySummitType);
+ }
+ });
+ }
+ }
+
+ private void rewriteSmsReply(List records) {
+ CollUtils.group(records, MsgCallRecord::getSubmitKey)
+ .forEach((submitKey, recordsBySubmitKey) -> {
+ Runnable function = () -> {
+ try {
+ SmsReplyDTO retReply = msgCallHelper.smsReply(submitKey);
+ String errorPhoneStr = retReply.getErrorPhone();
+ List errorPhones = StrUtil.split(errorPhoneStr, ",");
+ List replies = retReply.getResult();
+ Map currReplyMap = new HashMap<>();
+ if (replies != null && !replies.isEmpty()) {
+ replies.sort(Comparator.comparing(SmsReply::getReplyReplytime));
+ replies.forEach(w -> currReplyMap.putIfAbsent(w.getReplyMobile(), w));
+ }
+ List updates = new ArrayList<>();
+ for (MsgCallRecord w : recordsBySubmitKey) {
+ if (errorPhones.contains(w.getReceivePhone())) {
+ w.setReplyStatus(ReplyStatus.FAILED);
+ w.setReplyOn(LocalDateTime.now());
+ } else if (currReplyMap.containsKey(w.getReceivePhone())) {
+ SmsReply reply = currReplyMap.get(w.getReceivePhone());
+ w.setReplyOn(LocalDateTime.from(Instant.ofEpochMilli(reply.getReplyReplytime())));
+ w.setReplyContent(reply.getReplyContent());
+ w.setReplyStatus(ReplyStatus.SUCCESS);
+ }
+ if (w.getReplyOn() != null) {
+ updates.add(w);
+ }
+ }
+ msgCallRecordService.updateBatchById(updates);
+ } catch (Exception e) {
+ log.error("回复结果回填失败:{}", submitKey, e);
+ }
+ };
+ EXECUTOR.execute(function);
+ });
+ }
+
+ private void rewriteCallReply(List records) {
+ CollUtils.group(records, MsgCallRecord::getSubmitKey)
+ .forEach((submitKey, recordsBySubmitKey) -> {
+ Runnable function = () -> {
+ try {
+ List retReplies = msgCallHelper.callReply(submitKey);
+ Map replyMap = BizUtils.groupFirstMap(retReplies,
+ ReplyCallDTO::getRemoteNumber,
+ Comparator.comparing(ReplyCallDTO::getSendDate));
+ List updates = new ArrayList<>();
+ for (MsgCallRecord w : recordsBySubmitKey) {
+ ReplyCallDTO reply = replyMap.get(w.getReceivePhone());
+ if (reply != null) {
+ w.setReplyOn(LocalDateTimeUtil.of(reply.getSendDate()));
+ w.setReplyContent(reply.getDtmf());
+ w.setReplyStatus(ReplyStatus.SUCCESS);
+ updates.add(w);
+ }
+ }
+ msgCallRecordService.updateBatchById(updates);
+ } catch (Exception e) {
+ log.error("回复结果回填失败:{}", submitKey, e);
+ }
+ };
+ EXECUTOR.execute(function);
+ });
+ }
+
+}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/ConstructionManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/ConstructionManage.java
index 6a61c71..199289d 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/ConstructionManage.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/manage/ConstructionManage.java
@@ -599,33 +599,35 @@ public class ConstructionManage {
purchase.setXcfhxApplyFiles(req.getXcfhxApplyFiles());
purchase.setMatchXcfhx(req.getMatchXcfhx());
purchase.setXcfhxApplyRemark(req.getXcfhxApplyRemark());
- if (StrUtils.isBlank(purchase.getMhXcfhxReportFile()) ||
- req.getMhXcfhxReportFile().equals(purchase.getMhXcfhxReportFile())) {
- ApiResponse retFileInfo;
- File tmpFile = null;
- FileInputStream fis = null;
- try {
- tmpFile = mhFileClient.downloadToTmpFile(req.getMhXcfhxReportFile());
- String fileName = purchase.getBidName() + "-信创符合性测评报告." + FileUtil.getSuffix(tmpFile);
- fis = new FileInputStream(tmpFile);
- String mimeType = FileUtil.getMimeType(tmpFile.getPath());
- MockMultipartFile multipartFile = new MockMultipartFile(fileName, fileName, mimeType, fis);
- retFileInfo = fileController.upload(multipartFile, "default");
- } catch (IOException e) {
- log.error("信创报告上传失败", e);
- throw BizException.wrap("信创符合性测评报告上传失败");
- } finally {
- if (tmpFile != null) {
- tmpFile.deleteOnExit();
- }
- if (fis != null) {
- IOUtils.closeQuietly(fis);
+ if (Boolean.TRUE.equals(req.getMatchXcfhx())) {
+ if (StrUtils.isBlank(purchase.getMhXcfhxReportFile()) ||
+ req.getMhXcfhxReportFile().equals(purchase.getMhXcfhxReportFile())) {
+ ApiResponse retFileInfo;
+ File tmpFile = null;
+ FileInputStream fis = null;
+ try {
+ tmpFile = mhFileClient.downloadToTmpFile(req.getMhXcfhxReportFile());
+ String fileName = purchase.getBidName() + "-信创符合性测评报告." + FileUtil.getSuffix(tmpFile);
+ fis = new FileInputStream(tmpFile);
+ String mimeType = FileUtil.getMimeType(tmpFile.getPath());
+ MockMultipartFile multipartFile = new MockMultipartFile(fileName, fileName, mimeType, fis);
+ retFileInfo = fileController.upload(multipartFile, "default");
+ } catch (IOException e) {
+ log.error("信创报告上传失败", e);
+ throw BizException.wrap("信创符合性测评报告上传失败");
+ } finally {
+ if (tmpFile != null) {
+ tmpFile.deleteOnExit();
+ }
+ if (fis != null) {
+ IOUtils.closeQuietly(fis);
+ }
}
+ purchase.setXcfhxReportFiles(JSONUtil.toJsonStr(retFileInfo));
}
- purchase.setXcfhxReportFiles(JSONUtil.toJsonStr(retFileInfo));
+ purchase.setMhXcfhxReportRecordId(req.getMhXcfhxReportRecordId());
+ purchase.setMhXcfhxReportFile(req.getMhXcfhxReportFile());
}
- purchase.setMhXcfhxReportRecordId(req.getMhXcfhxReportRecordId());
- purchase.setMhXcfhxReportFile(req.getMhXcfhxReportFile());
xcfhxStateMachineUtil.pass(purchase);
purchaseService.updateById(purchase);
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/req/XcfhxApplyReq.java b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/req/XcfhxApplyReq.java
index 7daf9ba..6ff3452 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/req/XcfhxApplyReq.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/projectdeclared/model/req/XcfhxApplyReq.java
@@ -26,11 +26,9 @@ public class XcfhxApplyReq {
private Long bidId;
@ApiModelProperty("信创符合性测评报告文件")
- @NotBlank(message = "信创符合性测评报告文件不能为空")
private String mhXcfhxReportFile;
@ApiModelProperty("信创符合性测评记录ID")
- @NotBlank(message = "信创符合性测评记录ID不能为空")
private String mhXcfhxReportRecordId;
@ApiModelProperty("是否符合信创符合性要求")
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sms/manage/VerificationCodeManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/sms/manage/VerificationCodeManage.java
index 938c78e..a2f3453 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/sms/manage/VerificationCodeManage.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/sms/manage/VerificationCodeManage.java
@@ -2,18 +2,18 @@ package com.hz.pm.api.sms.manage;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.RandomUtil;
+import com.hz.pm.api.common.helper.MsgCallHelper;
+import com.hz.pm.api.external.sms.MhSmsClient;
import com.hz.pm.api.sms.constant.VerificationCodeType;
import com.hz.pm.api.sms.constant.VoiceSmsTemplateConst;
import com.hz.pm.api.sms.model.dto.VerifyCodeCacheDTO;
import com.hz.pm.api.sms.model.po.ReqVerificationCodePO;
import com.hz.pm.api.sms.utils.DateUtil;
import com.hz.pm.api.sms.utils.SmsRedisKeyUtils;
+import com.hz.pm.api.sys.model.enumeration.BizTypeEnum;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.cache.model.cache.CacheKey;
import com.ningdatech.cache.repository.CachePlusOps;
-import com.ningdatech.yxt.client.YxtClient;
-import com.ningdatech.yxt.model.cmd.SendSmsCmd;
-import com.ningdatech.yxt.model.cmd.SendSmsCmd.SendSmsContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@@ -34,7 +34,7 @@ import java.util.Objects;
@RequiredArgsConstructor
public class VerificationCodeManage {
- private final YxtClient yxtClient;
+ private final MsgCallHelper msgCallHelper;
private final CachePlusOps cachePlusOps;
public void sendVerificationCode(ReqVerificationCodePO req) {
@@ -62,22 +62,15 @@ public class VerificationCodeManage {
.build();
// 创建短信内容
- SendSmsCmd sendSmsCmd = new SendSmsCmd();
switch (codeType) {
case LOGIN: {
- SendSmsContext sendSmsCtx = new SendSmsContext();
- sendSmsCtx.setReceiveNumber(req.getMobile());
- sendSmsCtx.setContent(String.format(VoiceSmsTemplateConst.SMS_VERIFY_CODE, code, codeType.getExpireTime()));
- sendSmsCmd.setContextList(Collections.singletonList(sendSmsCtx));
-// sendSmsCmd.setSmsSignEnum(YxtSmsSignEnum.LS_BIG_DATA_BUREAU);
+ String content = String.format(VoiceSmsTemplateConst.SMS_VERIFY_CODE, code, codeType.getExpireTime());
+ msgCallHelper.sendMsg(content, req.getMobile(), BizTypeEnum.VERIFY_CODE);
}
break;
case EXPERT_REGISTER: {
- SendSmsContext sendSmsCtx = new SendSmsContext();
- sendSmsCtx.setReceiveNumber(req.getMobile());
- sendSmsCtx.setContent(String.format(VoiceSmsTemplateConst.EXPERT_REGISTER, code, codeType.getExpireTime()));
- sendSmsCmd.setContextList(Collections.singletonList(sendSmsCtx));
-// sendSmsCmd.setSmsSignEnum(YxtSmsSignEnum.LS_BIG_DATA_BUREAU);
+ String content = String.format(VoiceSmsTemplateConst.EXPERT_REGISTER, code, codeType.getExpireTime());
+ msgCallHelper.sendMsg(content, req.getMobile(), BizTypeEnum.VERIFY_CODE);
}
break;
default:
@@ -85,7 +78,6 @@ public class VerificationCodeManage {
}
// 发送 短信
- yxtClient.submitSmsTask(sendSmsCmd);
log.info("发送短信验证码:{} -> {}", req.getMobile(), code);
cachePlusOps.set(new CacheKey(cacheKey, Duration.ofMinutes(codeType.getExpireTime())), cache);
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sms/task/YxtPollingTask.java b/hz-pm-api/src/main/java/com/hz/pm/api/sms/task/YxtPollingTask.java
deleted file mode 100644
index e8eea91..0000000
--- a/hz-pm-api/src/main/java/com/hz/pm/api/sms/task/YxtPollingTask.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.hz.pm.api.sms.task;
-
-import com.ningdatech.yxt.client.YxtContext;
-import lombok.RequiredArgsConstructor;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-/**
- * @author liuxinxin
- * @date 2022/8/9 下午3:58
- * 音信通定时检查电话结果
- */
-@Component
-@RequiredArgsConstructor
-public class YxtPollingTask {
-
-
- private final YxtContext yxtContext;
-
- /**
- * 校验音信通结果数据
- * 每5分钟执行一次
- */
- @Scheduled(cron = "0 */1 * * * ?")
- public void smsMsgResultCheck() {
- yxtContext.smsMsgResultCheck();
- }
-}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sys/controller/NdMsgCallRecordController.java b/hz-pm-api/src/main/java/com/hz/pm/api/sys/controller/NdMsgCallRecordController.java
new file mode 100644
index 0000000..f96e425
--- /dev/null
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/sys/controller/NdMsgCallRecordController.java
@@ -0,0 +1,18 @@
+package com.hz.pm.api.sys.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.stereotype.Controller;
+
+/**
+ *
+ * 前端控制器
+ *
+ *
+ * @author WendyYang
+ * @since 2024-04-25
+ */
+@Controller
+@RequestMapping("/api.sys/ndMsgCallRecord")
+public class NdMsgCallRecordController {
+
+}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sys/manage/EarlyWarningManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/sys/manage/EarlyWarningManage.java
index 8b1c9bb..074c5e1 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/sys/manage/EarlyWarningManage.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/sys/manage/EarlyWarningManage.java
@@ -1,8 +1,6 @@
package com.hz.pm.api.sys.manage;
-import com.hz.pm.api.common.enumeration.CommonEnum;
import com.hz.pm.api.common.helper.UserInfoHelper;
-import com.hz.pm.api.meeting.helper.YxtClientHelper;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.enumeration.InstTypeEnum;
import com.hz.pm.api.projectlib.model.enumeration.WarningFlowTypeEnum;
@@ -13,7 +11,6 @@ import com.hz.pm.api.sys.model.entity.WflowEarlyWarningRecords;
import com.hz.pm.api.sys.service.IEarlyWarningRecordsService;
import com.hz.pm.api.sys.service.INotifyService;
import com.hz.pm.api.user.security.model.UserFullInfoDTO;
-import com.ningdatech.yxt.model.cmd.SendSmsCmd.SendSmsContext;
import com.wflow.enums.WarningNoticeTypeEnum;
import com.wflow.enums.WarningRuleTypeEnum;
import lombok.AllArgsConstructor;
@@ -37,13 +34,8 @@ import java.util.Objects;
public class EarlyWarningManage {
private final UserInfoHelper userInfoHelper;
-
private final NoticeManage noticeManage;
-
private final IEarlyWarningRecordsService earlyWarningRecordsService;
-
- private final YxtClientHelper yxtClientHelper;
-
private final INotifyService notifyService;
/**
@@ -147,14 +139,6 @@ public class EarlyWarningManage {
Notify notify = noticeManage.assemblyAuditNotify(user.getUserId(), project, content);
notify.setType(MsgTypeEnum.PROJECT_REVIEW.name());
notifyService.save(notify);
-
- //3.发短信
- if (noticeMethod.contains(String.valueOf(CommonEnum.MOBILE.getCode()))) {
- SendSmsContext context = new SendSmsContext();
- context.setReceiveNumber(user.getMobile());
- context.setContent(content);
- yxtClientHelper.sendSms(context);
- }
}
/**
@@ -263,13 +247,6 @@ public class EarlyWarningManage {
notify.setType(MsgTypeEnum.PROJECT_REVIEW.name());
notifyService.save(notify);
- //3.发短信
- if (noticeMethod.contains(String.valueOf(CommonEnum.MOBILE.getCode()))) {
- SendSmsContext context = new SendSmsContext();
- context.setReceiveNumber(user.getMobile());
- context.setContent(content);
- yxtClientHelper.sendSms(context);
- }
}
/**
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sys/mapper/MsgCallRecordMapper.java b/hz-pm-api/src/main/java/com/hz/pm/api/sys/mapper/MsgCallRecordMapper.java
new file mode 100644
index 0000000..75100a8
--- /dev/null
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/sys/mapper/MsgCallRecordMapper.java
@@ -0,0 +1,16 @@
+package com.hz.pm.api.sys.mapper;
+
+import com.hz.pm.api.sys.model.entity.MsgCallRecord;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ *
+ * Mapper 接口
+ *
+ *
+ * @author WendyYang
+ * @since 2024-04-25
+ */
+public interface MsgCallRecordMapper extends BaseMapper {
+
+}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sys/mapper/MsgCallRecordMapper.xml b/hz-pm-api/src/main/java/com/hz/pm/api/sys/mapper/MsgCallRecordMapper.xml
new file mode 100644
index 0000000..a770064
--- /dev/null
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/sys/mapper/MsgCallRecordMapper.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sys/model/entity/MsgCallRecord.java b/hz-pm-api/src/main/java/com/hz/pm/api/sys/model/entity/MsgCallRecord.java
new file mode 100644
index 0000000..8636fd1
--- /dev/null
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/sys/model/entity/MsgCallRecord.java
@@ -0,0 +1,124 @@
+package com.hz.pm.api.sys.model.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.hz.pm.api.sys.model.enumeration.BizTypeEnum;
+import com.hz.pm.api.sys.model.enumeration.SubmitTypeEnum;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ *
+ * 短信语音记录表
+ *
+ *
+ * @author WendyYang
+ * @since 2024-04-25
+ */
+@Data
+@TableName("ND_MSG_CALL_RECORD")
+@ApiModel(value = "NdMsgCallRecord对象")
+public class MsgCallRecord implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "ID", type = IdType.AUTO)
+ private Long id;
+
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createOn;
+
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateOn;
+
+ @TableField(fill = FieldFill.INSERT)
+ private Long createBy;
+
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Long updateBy;
+
+ /**
+ * 业务类型
+ */
+ private BizTypeEnum bizType;
+
+ /**
+ * 提交标识
+ */
+ private String submitKey;
+
+ /**
+ * 提交类型
+ */
+ private SubmitTypeEnum submitType;
+
+ /**
+ * 接收手机号
+ */
+ private String receivePhone;
+
+ /**
+ * 短信内容
+ */
+ private String content;
+
+ /**
+ * 模板编码
+ */
+ private String templateCode;
+
+ /**
+ * 是否需要回复
+ */
+ private Boolean needReply;
+
+ /**
+ * 发送状态:
+ */
+ private SendStatus sendStatus;
+
+ /**
+ * 回复状态
+ */
+ private ReplyStatus replyStatus;
+
+ /**
+ * 回复内容
+ */
+ private String replyContent;
+
+ /**
+ * 回复时间
+ */
+ private LocalDateTime replyOn;
+
+
+ /**
+ * 发送状态
+ */
+ public enum SendStatus {
+
+ SUCCESS,
+
+ FAILED
+
+ }
+
+ /**
+ * 发送状态
+ */
+ public enum ReplyStatus {
+
+ SUCCESS,
+
+ WAITING,
+
+ OVERTIME,
+
+ FAILED
+
+ }
+
+}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sys/model/enumeration/BizTypeEnum.java b/hz-pm-api/src/main/java/com/hz/pm/api/sys/model/enumeration/BizTypeEnum.java
new file mode 100644
index 0000000..5dcc120
--- /dev/null
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/sys/model/enumeration/BizTypeEnum.java
@@ -0,0 +1,32 @@
+package com.hz.pm.api.sys.model.enumeration;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ *
+ * BizTypeEnum
+ *
+ *
+ * @author WendyYang
+ * @since 16:13 2024/4/25
+ */
+@Getter
+@AllArgsConstructor
+public enum BizTypeEnum {
+
+ VERIFY_CODE("验证码"),
+
+ MEETING_ROSTER_CONFIRM("会议名单确认"),
+
+ EXPERT_LEAVE("专家请假"),
+
+ MEETING_CANCEL("会议取消"),
+
+ EXPERT_INVITE_STOP("会议取消"),
+
+ EXPERT_INVITE("专家邀请");
+
+ private final String desc;
+
+}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sys/model/enumeration/SubmitTypeEnum.java b/hz-pm-api/src/main/java/com/hz/pm/api/sys/model/enumeration/SubmitTypeEnum.java
new file mode 100644
index 0000000..5268ad2
--- /dev/null
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/sys/model/enumeration/SubmitTypeEnum.java
@@ -0,0 +1,17 @@
+package com.hz.pm.api.sys.model.enumeration;
+
+/**
+ *
+ * MsgTypeEnum
+ *
+ *
+ * @author WendyYang
+ * @since 15:26 2024/4/25
+ */
+public enum SubmitTypeEnum {
+
+ SMS,
+
+ CALL
+
+}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sys/service/IMsgCallRecordService.java b/hz-pm-api/src/main/java/com/hz/pm/api/sys/service/IMsgCallRecordService.java
new file mode 100644
index 0000000..64382c0
--- /dev/null
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/sys/service/IMsgCallRecordService.java
@@ -0,0 +1,16 @@
+package com.hz.pm.api.sys.service;
+
+import com.hz.pm.api.sys.model.entity.MsgCallRecord;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ *
+ * 服务类
+ *
+ *
+ * @author WendyYang
+ * @since 2024-04-25
+ */
+public interface IMsgCallRecordService extends IService {
+
+}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/sys/service/impl/MsgCallRecordServiceImpl.java b/hz-pm-api/src/main/java/com/hz/pm/api/sys/service/impl/MsgCallRecordServiceImpl.java
new file mode 100644
index 0000000..f206e2f
--- /dev/null
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/sys/service/impl/MsgCallRecordServiceImpl.java
@@ -0,0 +1,20 @@
+package com.hz.pm.api.sys.service.impl;
+
+import com.hz.pm.api.sys.model.entity.MsgCallRecord;
+import com.hz.pm.api.sys.mapper.MsgCallRecordMapper;
+import com.hz.pm.api.sys.service.IMsgCallRecordService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ *
+ * 服务实现类
+ *
+ *
+ * @author WendyYang
+ * @since 2024-04-25
+ */
+@Service
+public class MsgCallRecordServiceImpl extends ServiceImpl implements IMsgCallRecordService {
+
+}
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/workbench/manage/WorkbenchManage.java b/hz-pm-api/src/main/java/com/hz/pm/api/workbench/manage/WorkbenchManage.java
index 0c50072..031c587 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/workbench/manage/WorkbenchManage.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/workbench/manage/WorkbenchManage.java
@@ -319,6 +319,12 @@ public class WorkbenchManage {
.like(StrUtil.isNotBlank(req.getBuildOrg()), Project::getBuildOrgName, req.getBuildOrg())
.like(StrUtil.isNotBlank(req.getProjectName()), Project::getProjectName, req.getProjectName())
.in(Project::getBuildOrgCode, CollUtils.convert(viewUnitIds, String::valueOf))
+ // 评审金额
+ .ge(req.getReviewAmountMin() != null, Project::getReviewAmount, req.getReviewAmountMin())
+ .le(req.getReviewAmountMax() != null, Project::getReviewAmount, req.getReviewAmountMax())
+ // 下达金额
+ .ge(req.getApproveAmountMin() != null, Project::getApprovalAmount, req.getApproveAmountMin())
+ .ge(req.getApproveAmountMax() != null, Project::getApprovalAmount, req.getApproveAmountMax())
.eq(Project::getNewest, Boolean.TRUE)
.orderByDesc(Project::getUpdateOn);
switch (req.getProcessNode()) {
@@ -367,6 +373,8 @@ public class WorkbenchManage {
ProjectLibListItemVO item = new ProjectLibListItemVO();
item.setId(w.getId());
item.setProjectName(w.getProjectName());
+ // 项目申报
+ item.setFromType("1");
item.setProjectCode(w.getProjectCode());
item.setArea(w.getArea());
item.setAreaCode(w.getAreaCode());
@@ -382,6 +390,7 @@ public class WorkbenchManage {
item.setInstCode(w.getInstCode());
item.setIsHigherSuperOrg(w.getIsHigherSuperOrg());
item.setApprovedAmount(w.getApprovalAmount());
+ item.setReviewAmount(w.getReviewAmount());
item.setPrePlanProjectId(w.getPrePlanProjectId());
return item;
});
diff --git a/hz-pm-api/src/main/java/com/hz/pm/api/workbench/model/WorkbenchProjectLibReq.java b/hz-pm-api/src/main/java/com/hz/pm/api/workbench/model/WorkbenchProjectLibReq.java
index f64175f..198b827 100644
--- a/hz-pm-api/src/main/java/com/hz/pm/api/workbench/model/WorkbenchProjectLibReq.java
+++ b/hz-pm-api/src/main/java/com/hz/pm/api/workbench/model/WorkbenchProjectLibReq.java
@@ -5,6 +5,8 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import java.math.BigDecimal;
+
import static com.hz.pm.api.projectlib.handle.AbstractProcessHandle.ProcessNode;
/**
@@ -34,4 +36,16 @@ public class WorkbenchProjectLibReq extends PagePo {
@ApiModelProperty("申报单位名称")
private String buildOrg;
+ @ApiModelProperty("评审金额最小值")
+ private BigDecimal reviewAmountMin;
+
+ @ApiModelProperty("评审金额最大值")
+ private BigDecimal reviewAmountMax;
+
+ @ApiModelProperty("批复金额")
+ private BigDecimal approveAmountMin;
+
+ @ApiModelProperty("批复金额")
+ private BigDecimal approveAmountMax;
+
}
diff --git a/hz-pm-api/src/main/resources/application-dev.yml b/hz-pm-api/src/main/resources/application-dev.yml
index 86fc475..f8e0e3f 100644
--- a/hz-pm-api/src/main/resources/application-dev.yml
+++ b/hz-pm-api/src/main/resources/application-dev.yml
@@ -154,7 +154,7 @@ sa-token:
is-log: false
yxt:
-# wsdl-url: http://115.239.137.23:9501/ws/v1?wsdl
+ # wsdl-url: http://115.239.137.23:9501/ws/v1?wsdl
wsdl-url: classpath:/wsdl.xml
#账号
user-code: hzndkj
@@ -194,9 +194,8 @@ auth-code:
agent-login:
proxy:
secret-key: nqkwiqojg7g4eiypr3rb8s7nb4noa8b2
-sms:
- client-url: http://10.54.38.13:8081/mh-gateway/auth-single
-
+sms-send:
+ host: http://10.54.38.13:8081/mh-gateway/auth-single
# 提醒任务
reminder-task:
diff --git a/hz-pm-api/src/main/resources/application-prod.yml b/hz-pm-api/src/main/resources/application-prod.yml
index db0a928..df1f330 100644
--- a/hz-pm-api/src/main/resources/application-prod.yml
+++ b/hz-pm-api/src/main/resources/application-prod.yml
@@ -194,6 +194,10 @@ mh:
upload-url: http://10.54.38.13:8081/mh-gateway/oss/oss/uploadFileSkipLogin
purchase-notice:
open: false
+
+sms-send:
+ host: http://10.54.38.13:8081/mh-gateway/auth-single
+
sync-mh-company:
open: false
sync-mh-user:
diff --git a/hz-pm-api/src/test/java/com/hz/pm/api/external/MobileCallClientTest.java b/hz-pm-api/src/test/java/com/hz/pm/api/external/MobileCallClientTest.java
new file mode 100644
index 0000000..3cad7bf
--- /dev/null
+++ b/hz-pm-api/src/test/java/com/hz/pm/api/external/MobileCallClientTest.java
@@ -0,0 +1,42 @@
+package com.hz.pm.api.external;
+
+import com.hz.pm.api.AppTests;
+import com.hz.pm.api.common.helper.MsgCallHelper;
+import com.hz.pm.api.common.util.EnvironmentUtil;
+import com.hz.pm.api.external.model.dto.CallRetDTO;
+import com.hz.pm.api.sys.model.enumeration.BizTypeEnum;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ *
+ * MobileCallClientTest
+ *
+ *
+ * @author WendyYang
+ * @since 16:34 2024/4/26
+ */
+class MobileCallClientTest extends AppTests {
+
+ @Autowired
+ private MsgCallHelper msgCallHelper;
+
+ @Test
+ void sendCall() {
+ String format = String.format("【杭州数字信创】尊敬的专家您好,%s现邀请您作为专家参加%s会议,会议时间:%s,会议地点:%s。 确认参加请按 1,拒绝参加请按 2。请您选择",
+ "信创办", "测试语音", "2024年1月1日 12:30 至 2024年1月1日 12:30", "杭州市");
+ String ret = msgCallHelper.sendCall("19530651430", format, BizTypeEnum.EXPERT_INVITE);
+ System.out.println(ret);
+ }
+
+ @Test
+ void replyCall() {
+ System.out.println(msgCallHelper.callReply("3086259928697016320"));
+ }
+}
\ No newline at end of file
diff --git a/hz-pm-api/src/test/resources/application-dev.yml b/hz-pm-api/src/test/resources/application-dev.yml
index 66382c6..64b21b5 100644
--- a/hz-pm-api/src/test/resources/application-dev.yml
+++ b/hz-pm-api/src/test/resources/application-dev.yml
@@ -193,5 +193,7 @@ auth-code:
agent-login:
proxy:
secret-key: nqkwiqojg7g4eiypr3rb8s7nb4noa8b2
-sms:
- client-url: http://10.54.38.13:8081/mh-gateway/auth-single
\ No newline at end of file
+sms-send:
+ host: http://10.54.38.13:8081/mh-gateway/auth-single
+mobile-call:
+ host: http://36.20.16.36:18181/blue_esl_api
\ No newline at end of file
diff --git a/hz-pm-gen/src/main/java/com/hz/pm/gen/config/CodeGen.java b/hz-pm-gen/src/main/java/com/hz/pm/gen/config/CodeGen.java
index 901952d..189fde4 100644
--- a/hz-pm-gen/src/main/java/com/hz/pm/gen/config/CodeGen.java
+++ b/hz-pm-gen/src/main/java/com/hz/pm/gen/config/CodeGen.java
@@ -55,7 +55,7 @@ public class CodeGen {
}
public static void main(String[] args) {
- generate("WendyYang", "projectdeclared", PATH_YYD, "nd_project_review");
+ generate("WendyYang", "sys", PATH_YYD, "nd_msg_call_record");
}
}