|
@@ -0,0 +1,330 @@
|
|
|
+package com.fs.app.service;
|
|
|
+
|
|
|
+import com.fs.common.core.redis.RedisCache;
|
|
|
+import com.fs.common.utils.StringUtils;
|
|
|
+import com.fs.common.utils.date.DateUtil;
|
|
|
+import com.fs.course.config.CourseMaConfig;
|
|
|
+import com.fs.course.domain.FsCourseWatchLog;
|
|
|
+import com.fs.course.service.IFsCourseWatchLogService;
|
|
|
+import com.fs.ipad.IpadSendUtils;
|
|
|
+import com.fs.ipad.vo.*;
|
|
|
+import com.fs.qw.domain.QwUser;
|
|
|
+import com.fs.qw.mapper.QwExternalContactMapper;
|
|
|
+import com.fs.qw.mapper.QwUserMapper;
|
|
|
+import com.fs.qw.vo.QwSopCourseFinishTempSetting;
|
|
|
+import com.fs.qwApi.param.QwExternalContactHParam;
|
|
|
+import com.fs.sop.domain.QwSopLogs;
|
|
|
+import com.fs.sop.service.IQwSopLogsService;
|
|
|
+import com.fs.sop.service.impl.QwSopLogsServiceImpl;
|
|
|
+import com.fs.wxwork.dto.*;
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@AllArgsConstructor
|
|
|
+public class IpadSendServer {
|
|
|
+
|
|
|
+ private final QwUserMapper qwUserMapper;
|
|
|
+ private final IpadSendUtils ipadSendUtils;
|
|
|
+ private final IQwSopLogsService qwSopLogsService;
|
|
|
+ private final QwExternalContactMapper qwExternalContactMapper;
|
|
|
+ private final IFsCourseWatchLogService watchLogService;
|
|
|
+ private final RedisCache redisCache;
|
|
|
+
|
|
|
+ private void sendMiniProgram(BaseVo vo, QwSopCourseFinishTempSetting.Setting content, Map<String, CourseMaConfig> miniMap) {
|
|
|
+ CourseMaConfig courseMaConfig = miniMap.get(content.getMiniprogramAppid());
|
|
|
+ // 小程序
|
|
|
+ MiniProgramVo miniProgramVo = MiniProgramVo.builder()
|
|
|
+ .desc(content.getMiniprogramTitle())
|
|
|
+ .title(courseMaConfig.getName())
|
|
|
+ .weappIconUrl(courseMaConfig.getLog())
|
|
|
+ .imgUrl(content.getMiniprogramPicUrl())
|
|
|
+ .username(courseMaConfig.getUsername() + "@app")
|
|
|
+ .pagepath(content.getMiniprogramPage())
|
|
|
+ .appid(content.getMiniprogramAppid())
|
|
|
+ .build();
|
|
|
+ miniProgramVo.setBase(vo);
|
|
|
+ WxWorkResponseDTO<WxWorkSendAppMsgRespDTO> resp = ipadSendUtils.sendMiniProgram(miniProgramVo);
|
|
|
+ if (resp.getErrcode() != 0) {
|
|
|
+ log.debug("ID:{}-ipad接口请求返回异常:{}", vo.getId(), resp.getErrmsg());
|
|
|
+ content.setSendStatus(2);
|
|
|
+ content.setSendRemarks("发送失败:" + resp.getErrmsg());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void sendFile(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
|
|
|
+ FileVo fileVo = FileVo.builder()
|
|
|
+ .url(content.getFileUrl())
|
|
|
+ .build();
|
|
|
+ fileVo.setBase(vo);
|
|
|
+ WxWorkResponseDTO<WxwSendCDNFileMsgRespDTO> resp = ipadSendUtils.sendFile(fileVo);
|
|
|
+ if (resp.getErrcode() != 0) {
|
|
|
+ log.debug("ID:{}-ipad接口请求返回异常:{}", vo.getId(), resp.getErrmsg());
|
|
|
+ content.setSendStatus(2);
|
|
|
+ content.setSendRemarks("发送失败:" + resp.getErrmsg());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void sendTxt(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
|
|
|
+ TxtVo txtVo = TxtVo.builder().content(content.getValue()).build();
|
|
|
+ txtVo.setBase(vo);
|
|
|
+ WxWorkResponseDTO<WxWorkSendTextMsgRespDTO> resp = ipadSendUtils.sendTxt(txtVo);
|
|
|
+ if (resp.getErrcode() != 0) {
|
|
|
+ log.debug("ID:{}-ipad接口请求返回异常:{}", vo.getId(), resp.getErrmsg());
|
|
|
+ content.setSendStatus(2);
|
|
|
+ content.setSendRemarks("发送失败:" + resp.getErrmsg());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void sendImg(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
|
|
|
+ FileVo imgVo = FileVo.builder().url(content.getImgUrl()).build();
|
|
|
+ imgVo.setBase(vo);
|
|
|
+ WxWorkResponseDTO<WxwSendCDNImgMsgRespDTO> resp = ipadSendUtils.sendImg(imgVo);
|
|
|
+ if (resp.getErrcode() != 0) {
|
|
|
+ log.debug("ID:{}-ipad接口请求返回异常:{}", vo.getId(), resp.getErrmsg());
|
|
|
+ content.setSendStatus(2);
|
|
|
+ content.setSendRemarks("发送失败:" + resp.getErrmsg());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void sendLink(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
|
|
|
+ // 文本
|
|
|
+ LinkVo linkVo = LinkVo.builder()
|
|
|
+ .title(content.getLinkTitle())
|
|
|
+ .content(content.getLinkDescribe())
|
|
|
+ .url(content.getLinkUrl())
|
|
|
+ .imgUrl(content.getLinkImageUrl())
|
|
|
+ .build();
|
|
|
+ linkVo.setBase(vo);
|
|
|
+ WxWorkResponseDTO<WxwSendLinkMsgRespDTO> resp = ipadSendUtils.sendLink(linkVo);
|
|
|
+ if (resp.getErrcode() != 0) {
|
|
|
+ log.debug("ID:{}-ipad接口请求返回异常:{}", vo.getId(), resp.getErrmsg());
|
|
|
+ content.setSendStatus(2);
|
|
|
+ content.setSendRemarks("发送失败:" + resp.getErrmsg());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void sendVideo(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
|
|
|
+ FileVo videoVo = FileVo.builder()
|
|
|
+ .url(content.getVideoUrl())
|
|
|
+ .build();
|
|
|
+ videoVo.setBase(vo);
|
|
|
+ WxWorkResponseDTO<WxwSendCDNVideoMsgRespDTO> resp = ipadSendUtils.sendVideo(videoVo);
|
|
|
+ if (resp.getErrcode() != 0) {
|
|
|
+ log.debug("ID:{}-ipad接口请求返回异常:{}", vo.getId(), resp.getErrmsg());
|
|
|
+ content.setSendStatus(2);
|
|
|
+ content.setSendRemarks("发送失败:" + resp.getErrmsg());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void sendVoice(BaseVo vo, QwSopCourseFinishTempSetting.Setting content) {
|
|
|
+ if (StringUtils.isEmpty(content.getVoiceUrl()) || StringUtils.isEmpty(content.getVoiceDuration())) {
|
|
|
+ log.debug("语音未生成无法发送,转文字发送:{}", vo);
|
|
|
+ sendTxt(vo, content);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ FileVo voiceVo = FileVo.builder()
|
|
|
+ .url(content.getVoiceUrl())
|
|
|
+ .voiceTime(Integer.parseInt(content.getVoiceDuration()))
|
|
|
+ .build();
|
|
|
+ voiceVo.setBase(vo);
|
|
|
+ WxWorkResponseDTO<WxwSendCDNVoiceMsgRespDTO> resp = ipadSendUtils.sendVoice(voiceVo);
|
|
|
+ if (resp.getErrcode() != 0) {
|
|
|
+ log.debug("ID:{}-ipad接口请求返回异常:{}", vo.getId(), resp.getErrmsg());
|
|
|
+ content.setSendStatus(2);
|
|
|
+ content.setSendRemarks("发送失败:" + resp.getErrmsg());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean isSend(QwUser qwUser) {
|
|
|
+ // 判断企微发送方式是否是ipad
|
|
|
+ if (qwUser.getSendMsgType() == 0) {
|
|
|
+ log.debug("企微用户:ID:{} 名称:{} 发送方式:{}", qwUser.getId(), qwUser.getQwUserName(), qwUser.getSendMsgType().toString());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 判断是否信息准确
|
|
|
+ if (org.springframework.util.StringUtils.isEmpty(qwUser.getUid())) {
|
|
|
+ log.debug("企微用户:ID:{} 名称:{}", qwUser.getId(), qwUser.getQwUserName());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 是否已经授权服务器地址
|
|
|
+ if (qwUser.getServerId() == null) {
|
|
|
+ log.debug("企微用户:ID:{} 名称:{} 未绑定AI主机", qwUser.getId(), qwUser.getQwUserName());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // ipad状态是否是登录状态
|
|
|
+ if (qwUser.getIpadStatus() == 0) {
|
|
|
+ log.debug("企微用户:ID:{} 名称:{} 未登录uid:{},serveID:{}", qwUser.getId(), qwUser.getQwUserName(), qwUser.getUid(), qwUser.getServerId());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 更新信息使用的类
|
|
|
+ QwUser updateQwUser = new QwUser();
|
|
|
+ try {
|
|
|
+ // 调用ipad接口判断是否真实登录
|
|
|
+ WxLoginResp login = ipadSendUtils.isLogin(qwUser.getUid(), qwUser.getServerId());
|
|
|
+ if (login.getLoginType() == 0) {
|
|
|
+ updateQwUser.setId(qwUser.getId());
|
|
|
+ updateQwUser.setRemark("AI未初始化");
|
|
|
+ updateQwUser.setIpadStatus(0);
|
|
|
+ qwUserMapper.updateById(updateQwUser);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (login.getLoginType() == 1) {
|
|
|
+ updateQwUser.setId(qwUser.getId());
|
|
|
+ updateQwUser.setRemark("未登录");
|
|
|
+ updateQwUser.setIpadStatus(0);
|
|
|
+ qwUserMapper.updateById(updateQwUser);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!login.getUser_info().isLogin()) {
|
|
|
+ updateQwUser.setId(qwUser.getId());
|
|
|
+ updateQwUser.setRemark("登录状态异常");
|
|
|
+ updateQwUser.setIpadStatus(0);
|
|
|
+ qwUserMapper.updateById(updateQwUser);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ log.debug("QwUserID:{}, AI主机信息:{}", qwUser.getId(), login);
|
|
|
+ } catch (Exception e) {
|
|
|
+ updateQwUser.setId(qwUser.getId());
|
|
|
+ updateQwUser.setRemark("登录状态异常");
|
|
|
+ updateQwUser.setIpadStatus(0);
|
|
|
+ qwUserMapper.updateById(updateQwUser);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean isSendLogs(QwSopLogs qwSopLogs, QwSopCourseFinishTempSetting setting, QwUser qwUser) {
|
|
|
+
|
|
|
+ if(redisCache.getCacheObject("qw:user:id:" + qwUser.getId()) != null){
|
|
|
+ log.info("频率异常不发送:{}", qwUser.getQwUserName());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean noSop = qwSopLogs.getSendType() != 3 && qwSopLogs.getSendType() != 7;
|
|
|
+
|
|
|
+ if (qwSopLogs.getExpiryTime() == null && noSop) {
|
|
|
+ // 作废消息
|
|
|
+ log.warn("SOP_LOG_ID:{}, SOP任务被删除", qwSopLogs.getId());
|
|
|
+ qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "SOP任务被删除");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ LocalDateTime sendTime = DateUtil.stringToLocalDateTime(qwSopLogs.getSendTime());
|
|
|
+ LocalDateTime expiryDateTime;
|
|
|
+
|
|
|
+ // 判断是否过期
|
|
|
+ if(qwSopLogs.getSendType() == 3 || qwSopLogs.getSendType() == 7){
|
|
|
+ expiryDateTime = sendTime.plusHours(12);
|
|
|
+ }else{
|
|
|
+ expiryDateTime = sendTime.plusHours(qwSopLogs.getExpiryTime());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (LocalDateTime.now().isAfter(expiryDateTime) ) {
|
|
|
+ // 作废消息
|
|
|
+ log.warn("SOP_LOG_ID:{}, 已过期,不发送", qwSopLogs.getId());
|
|
|
+ qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "已过期,不发送");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (setting.getCourseType() == null && noSop && setting.getType() == 2) {
|
|
|
+ log.warn("SOP_LOG_ID:{}, 模板未选消息类型,不发送", qwSopLogs.getId());
|
|
|
+ qwSopLogsService.updateQwSopLogsByWatchLogType(qwSopLogs.getId(), "模板未选消息类型,不发送");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (qwSopLogs.getSendType() != 12 && noSop) {
|
|
|
+ // 客户的信息
|
|
|
+ QwExternalContactHParam contactHParam = new QwExternalContactHParam();
|
|
|
+ contactHParam.setUserId(qwUser.getQwUserId().trim());
|
|
|
+ contactHParam.setExternalUserId(qwSopLogs.getExternalUserId().trim());
|
|
|
+ contactHParam.setCorpId(qwUser.getCorpId().trim());
|
|
|
+ Integer courseType = setting.getCourseType();
|
|
|
+ if (setting.getType() == 2 && courseType != 0) {// 课程消息,进行复杂的条件判断
|
|
|
+ log.debug("企微查询:{}", contactHParam);
|
|
|
+ Long qwExternalContactId = qwExternalContactMapper.getQwExternalContactId(contactHParam);
|
|
|
+ FsCourseWatchLog watchLog = watchLogService.getWatchCourseLogVideoBySop(
|
|
|
+ setting.getVideoId().longValue(),
|
|
|
+ String.valueOf(qwUser.getId()),
|
|
|
+ qwExternalContactId
|
|
|
+ );
|
|
|
+ log.debug("ID:{}-看课记录参数:videoID:{}, qwUserID:{}, extID:{}", qwSopLogs.getId(), setting.getVideoId().longValue(), qwUser.getId(), qwExternalContactId);
|
|
|
+ log.debug("ID:{}-看课记录:{}", qwSopLogs.getId(), watchLog);
|
|
|
+ String logId = qwSopLogs.getId();
|
|
|
+ if (watchLog != null) {
|
|
|
+ //新逻辑
|
|
|
+ if (!QwSopLogsServiceImpl.isCourseTypeValid(courseType, watchLog.getLogType())) {
|
|
|
+ // 作废消息
|
|
|
+ log.warn("SOP_LOG_ID:{}, 看课状态未满足,不发送", qwSopLogs.getId());
|
|
|
+ qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "看课状态未满足,不发送");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ log.warn("SOP_LOG_ID:{}, 无观看记录,不发送", qwSopLogs.getId());
|
|
|
+ qwSopLogsService.updateQwSopLogsByWatchLogType(logId, "无观看记录,不发送");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void send(QwSopCourseFinishTempSetting.Setting content, QwUser qwUser, QwSopLogs qwSopLogs, Map<String, CourseMaConfig> miniMap) {
|
|
|
+ BaseVo vo = new BaseVo();
|
|
|
+ vo.setId(Long.parseLong(qwSopLogs.getId()));
|
|
|
+ vo.setRoom(qwSopLogs.getSendType() == 12);
|
|
|
+ vo.setUuid(qwUser.getUid());
|
|
|
+ vo.setExId(qwSopLogs.getExternalUserId());
|
|
|
+ vo.setServerId(qwUser.getServerId());
|
|
|
+ try {
|
|
|
+ content.setSendStatus(1);
|
|
|
+ switch (content.getContentType()) {
|
|
|
+ case "1":
|
|
|
+ // 文本
|
|
|
+ sendTxt(vo, content);
|
|
|
+ break;
|
|
|
+ case "2":
|
|
|
+ // 图片
|
|
|
+ sendImg(vo, content);
|
|
|
+ break;
|
|
|
+ case "9":
|
|
|
+ case "3":
|
|
|
+ // 链接
|
|
|
+ sendLink(vo, content);
|
|
|
+ break;
|
|
|
+ case "4":
|
|
|
+ sendMiniProgram(vo, content, miniMap);
|
|
|
+ break;
|
|
|
+ case "5":
|
|
|
+ // 文件
|
|
|
+ sendFile(vo, content);
|
|
|
+ break;
|
|
|
+ case "6":
|
|
|
+ // 视频
|
|
|
+ sendVideo(vo, content);
|
|
|
+ break;
|
|
|
+ case "7":
|
|
|
+ // 语音
|
|
|
+ sendVoice(vo, content);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ // 未知类型,记录警告
|
|
|
+ log.error("SOP_LOG_ID:{}错误的发送类型: {}", qwSopLogs.getId(), content.getContentType());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("ID:" + qwSopLogs.getId() + "-发送失败QW_SOP_ID:" + qwSopLogs.getId(), e);
|
|
|
+ content.setSendStatus(2);
|
|
|
+ content.setSendRemarks("发送失败:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void loginOut(QwUser user) {
|
|
|
+ ipadSendUtils.loginOut(user.getUid(), user.getServerId());
|
|
|
+ }
|
|
|
+}
|