| | |
| | | import cn.iocoder.yudao.module.wxcp.dal.mysql.notice.WxCpNoticeMapper; |
| | | import cn.iocoder.yudao.module.wxcp.enums.activity.WxCpPushScopeEnum; |
| | | import cn.iocoder.yudao.module.wxcp.enums.notice.WxCpNoticeStatusEnum; |
| | | import cn.iocoder.yudao.module.wxcp.enums.notice.WxCpNoticeTypeEnum; |
| | | import cn.iocoder.yudao.module.wxcp.service.push.WxCpMessagePushService; |
| | | import cn.iocoder.yudao.module.system.dal.dataobject.storage.SystemStorageBlobDO; |
| | | import cn.iocoder.yudao.module.system.service.storage.SystemStorageBlobService; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.io.File; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Objects; |
| | | |
| | |
| | | private WxCpNoticeMapper wxcpNoticeMapper; |
| | | @Resource |
| | | private WxCpMessagePushService messagePushService; |
| | | @Resource |
| | | private SystemStorageBlobService storageBlobService; |
| | | |
| | | /** 企业微信文件消息上限 20MB */ |
| | | private static final long MAX_FILE_SIZE = 20L * 1024L * 1024L; |
| | | |
| | | @Override |
| | | public Long createNotice(WxCpNoticeSaveReqVO createReqVO) { |
| | | WxCpNoticeDO notice = BeanUtils.toBean(createReqVO, WxCpNoticeDO.class); |
| | | if (notice.getNoticeType() == null) { |
| | | notice.setNoticeType(WxCpNoticeTypeEnum.TEXT.getType()); |
| | | } |
| | | notice.setStatus(WxCpNoticeStatusEnum.DRAFT.getStatus()); |
| | | notice.setPushStatus(0); |
| | | // 推送范围选填,不传默认全员;推送时还能在弹窗里改 |
| | |
| | | scope = WxCpPushScopeEnum.ALL.getScope(); |
| | | } |
| | | |
| | | // 通知用纯文本推送:没有可跳转的详情页,而 textcard 类型强制要求 url |
| | | WxCpPushResultVO result = messagePushService.pushText( |
| | | buildPushContent(notice), scope, target); |
| | | // 推送时允许重新选择模板类型;未选择则沿用通知上保存的模板 |
| | | Integer noticeType = pushReqVO.getNoticeType() != null |
| | | ? pushReqVO.getNoticeType() |
| | | : (notice.getNoticeType() != null ? notice.getNoticeType() : WxCpNoticeTypeEnum.TEXT.getType()); |
| | | String summary = StrUtil.blankToDefault(pushReqVO.getSummary(), notice.getSummary()); |
| | | String linkUrl = StrUtil.blankToDefault(pushReqVO.getLinkUrl(), notice.getLinkUrl()); |
| | | String linkBtnText = StrUtil.blankToDefault(pushReqVO.getLinkBtnText(), notice.getLinkBtnText()); |
| | | String coverUrl = StrUtil.blankToDefault(pushReqVO.getCoverUrl(), notice.getCoverUrl()); |
| | | Long fileBlobId = pushReqVO.getFileBlobId() != null ? pushReqVO.getFileBlobId() : notice.getFileBlobId(); |
| | | String fileName = StrUtil.blankToDefault(pushReqVO.getFileName(), notice.getFileName()); |
| | | |
| | | // 按本次选择的模板类型校验必填项 |
| | | if (Objects.equals(noticeType, WxCpNoticeTypeEnum.TEXT.getType()) |
| | | && StrUtil.isBlank(notice.getContent())) { |
| | | throw exception(NOTICE_CONTENT_REQUIRED); |
| | | } |
| | | if ((Objects.equals(noticeType, WxCpNoticeTypeEnum.CARD.getType()) |
| | | || Objects.equals(noticeType, WxCpNoticeTypeEnum.NEWS.getType())) |
| | | && StrUtil.isBlank(linkUrl)) { |
| | | throw exception(NOTICE_LINK_URL_REQUIRED); |
| | | } |
| | | if (Objects.equals(noticeType, WxCpNoticeTypeEnum.FILE.getType()) && fileBlobId == null) { |
| | | throw exception(NOTICE_FILE_REQUIRED); |
| | | } |
| | | |
| | | WxCpPushResultVO result; |
| | | if (Objects.equals(noticeType, WxCpNoticeTypeEnum.CARD.getType())) { |
| | | result = messagePushService.pushCard(notice.getTitle(), |
| | | StrUtil.blankToDefault(summary, notice.getContent()), |
| | | linkUrl, StrUtil.blankToDefault(linkBtnText, "去填报"), scope, target); |
| | | } else if (Objects.equals(noticeType, WxCpNoticeTypeEnum.FILE.getType())) { |
| | | result = pushFileNotice(fileBlobId, fileName, notice, scope, target); |
| | | } else if (Objects.equals(noticeType, WxCpNoticeTypeEnum.NEWS.getType())) { |
| | | result = messagePushService.pushNews(notice.getTitle(), |
| | | StrUtil.blankToDefault(summary, notice.getContent()), |
| | | linkUrl, coverUrl, scope, target); |
| | | } else { |
| | | result = messagePushService.pushText(buildPushContent(notice), scope, target); |
| | | } |
| | | |
| | | if (Boolean.TRUE.equals(result.getSuccess())) { |
| | | wxcpNoticeMapper.updateById(WxCpNoticeDO.builder() |
| | |
| | | } |
| | | |
| | | /** |
| | | * 文件通知:从系统附件中心取文件,交给推送服务上传企业微信并发送 |
| | | */ |
| | | private WxCpPushResultVO pushFileNotice(Long fileBlobId, String fileName, WxCpNoticeDO notice, |
| | | Integer scope, String target) { |
| | | if (fileBlobId == null) { |
| | | throw exception(NOTICE_FILE_REQUIRED); |
| | | } |
| | | SystemStorageBlobDO blob = storageBlobService.getStorageBlob(fileBlobId); |
| | | if (blob == null) { |
| | | throw exception(NOTICE_FILE_NOT_EXISTS); |
| | | } |
| | | if (blob.getByteSize() != null && blob.getByteSize() > MAX_FILE_SIZE) { |
| | | throw exception(NOTICE_FILE_TOO_LARGE); |
| | | } |
| | | File file = storageBlobService.getPublicFile(blob.getUidFilename(), blob.getResourceKey()); |
| | | if (file == null || !file.exists()) { |
| | | throw exception(NOTICE_FILE_NOT_EXISTS); |
| | | } |
| | | String actualFileName = StrUtil.blankToDefault(fileName, blob.getOriginalFilename()); |
| | | return messagePushService.pushFile(file, actualFileName, buildPushContent(notice), scope, target); |
| | | } |
| | | |
| | | /** |
| | | * 按模板类型校验必填项 |
| | | */ |
| | | private void validateNoticeByType(WxCpNoticeSaveReqVO reqVO) { |
| | | Integer type = reqVO.getNoticeType() != null |
| | | ? reqVO.getNoticeType() : WxCpNoticeTypeEnum.TEXT.getType(); |
| | | if (Objects.equals(type, WxCpNoticeTypeEnum.TEXT.getType()) |
| | | && StrUtil.isBlank(reqVO.getContent())) { |
| | | throw exception(NOTICE_CONTENT_REQUIRED); |
| | | } |
| | | if ((Objects.equals(type, WxCpNoticeTypeEnum.CARD.getType()) |
| | | || Objects.equals(type, WxCpNoticeTypeEnum.NEWS.getType())) |
| | | && StrUtil.isBlank(reqVO.getLinkUrl())) { |
| | | throw exception(NOTICE_LINK_URL_REQUIRED); |
| | | } |
| | | if (Objects.equals(type, WxCpNoticeTypeEnum.FILE.getType()) |
| | | && reqVO.getFileBlobId() == null) { |
| | | throw exception(NOTICE_FILE_REQUIRED); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 拼装推送正文:标题加粗样式用不了,改用【】包裹;过长则截断并提示 |
| | | */ |
| | | private String buildPushContent(WxCpNoticeDO notice) { |