diff --git a/src/main/java/com/budwk/app/base/sms/SmsService.java b/src/main/java/com/budwk/app/base/sms/SmsService.java index 4003f203..5dd46771 100644 --- a/src/main/java/com/budwk/app/base/sms/SmsService.java +++ b/src/main/java/com/budwk/app/base/sms/SmsService.java @@ -107,6 +107,20 @@ public interface SmsService { */ void massSendTextCard(List loginNames, String title, String content, String pcUrl, String mobileUrl); + /** + * 群发短信文本卡片消息 + * @param loginNames 接收人工号列表(必填,不能为空列表) + * @param content 卡片内容(必填) + * @param pcUrl PC端跳转链接(必填) + * @param mobileUrl 移动端跳转链接(必填) + * @param type 类型(如:体检管理) + * @param projectName 项目名称 + * @param remark 备注信息 + * @return + */ + void massSendTextCard(List loginNames, String content, String pcUrl, String mobileUrl, String type, String projectName, String remark); + + /** * 群发图文卡片消息 * @param loginNames 接收人工号列表(必填,不能为空列表) diff --git a/src/main/java/com/budwk/app/base/sms/impl/ncu/SmsNcuServiceImpl.java b/src/main/java/com/budwk/app/base/sms/impl/ncu/SmsNcuServiceImpl.java index 59217093..5ccaebf4 100644 --- a/src/main/java/com/budwk/app/base/sms/impl/ncu/SmsNcuServiceImpl.java +++ b/src/main/java/com/budwk/app/base/sms/impl/ncu/SmsNcuServiceImpl.java @@ -1,21 +1,29 @@ package com.budwk.app.base.sms.impl.ncu; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.budwk.app.base.sms.SmsService; import com.budwk.app.base.sms.impl.ncu.util.SmsTokenUtil; +import com.budwk.app.sys.models.Sys_msg; +import com.budwk.app.sys.models.Sys_msg_user; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.web.commons.base.Globals; import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.formula.functions.T; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.json.Json; import org.nutz.lang.Lang; +import org.nutz.lang.Times; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -27,145 +35,314 @@ import java.util.stream.Stream; @IocBean public class SmsNcuServiceImpl implements SmsService { - @Inject - private SmsTokenUtil smsTokenUtil; + @Inject + private SmsTokenUtil smsTokenUtil; + @Inject + private Dao dao; - private static final String SEND_MSG_URL = "https://poa.ncu.edu.cn/apis/messagecenter/v1/poaMessage/messageSend"; - private static final String APP_ID = "72e34a101d3011f1a74cbae5193504f4"; - private static final String TEMPLATE_ID = "MT1773223005000"; + private static final String SEND_MSG_URL = "https://poa.ncu.edu.cn/apis/messagecenter/v1/poaMessage/messageSend"; + private static final String APP_ID = "72e34a101d3011f1a74cbae5193504f4"; + private static final String TEMPLATE_ID = "MT1773223005000"; - @Override - public void sendSingleMessage(String loginName, String content) { - this.sendSingleMessage(loginName, "智慧工会", content); - } + @Override + public void sendSingleMessage(String loginName, String content) { + this.sendSingleMessage(loginName, "智慧工会", content); + } - @Override - public void sendSingleMessage(String loginName, String title, String content) { - this.massSendMessage(List.of(loginName), title, content); - } + @Override + public void sendSingleMessage(String loginName, String title, String content) { + this.massSendMessage(List.of(loginName), title, content); + } - @Override - public void sendSingleTextCard(String loginName, String content, String pcUrl, String mobileUrl) { - this.sendSingleTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl); - } + @Override + public void sendSingleTextCard(String loginName, String content, String pcUrl, String mobileUrl) { + this.sendSingleTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl); + } - @Override - public void sendSingleTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl) { - this.massSendTextCard(List.of(loginName), title, content, pcUrl, mobileUrl); - } + @Override + public void sendSingleTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl) { + this.massSendTextCard(List.of(loginName), title, content, pcUrl, mobileUrl); + } - @Override - public void sendSinglePicTextCard(String loginName, String content, String pcUrl, String mobileUrl, String picUrl) { - this.sendSinglePicTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl, picUrl); - } + @Override + public void sendSinglePicTextCard(String loginName, String content, String pcUrl, String mobileUrl, String picUrl) { + this.sendSinglePicTextCard(loginName, "智慧工会", content, pcUrl, mobileUrl, picUrl); + } - @Override - public void sendSinglePicTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl, String picUrl) { - this.massSendPicTextCard(List.of(loginName), title, content, pcUrl, mobileUrl, picUrl); - } + @Override + public void sendSinglePicTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl, String picUrl) { + this.massSendPicTextCard(List.of(loginName), title, content, pcUrl, mobileUrl, picUrl); + } - @Override - public void massSendMessage(List loginNames, String content) { - this.massSendMessage(loginNames, "智慧工会", content); - } + @Override + public void massSendMessage(List loginNames, String content) { + this.massSendMessage(loginNames, "智慧工会", content); + } - @Override - public void massSendMessage(List loginNames, String title, String content) { - String list = String.join(",", loginNames); - this.doSend("text", list, title, content, null, null, null); - } + @Override + public void massSendMessage(List loginNames, String title, String content) { + this.doSend("text", loginNames, title, content, null, null, null); + } - @Override - public void massSendTextCard(List loginNames, String content, String pcUrl, String mobileUrl) { - this.massSendTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl); - } + @Override + public void massSendTextCard(List loginNames, String content, String pcUrl, String mobileUrl) { + this.massSendTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl); + } - @Override - public void massSendTextCard(List loginNames, String title, String content, String pcUrl, String mobileUrl) { - String list = String.join(",", loginNames); - this.doSend("textCard", list, title, content, pcUrl, mobileUrl, null); - } + @Override + public void massSendTextCard(List loginNames, String title, String content, String pcUrl, String mobileUrl) { + this.doSend("textCard", loginNames, title, content, pcUrl, mobileUrl, null); + } - @Override - public void massSendPicTextCard(List loginNames, String content, String pcUrl, String mobileUrl, String picUrl) { - this.massSendPicTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl, picUrl); - } + @Override + public void massSendTextCard(List loginNames, String content, String pcUrl, String mobileUrl, String type, String projectName, String remark) { + this.doSendAndMessageRecordByType("textCard", loginNames, "智慧工会", content, pcUrl, mobileUrl, null, type, projectName, remark); + } - @Override - public void massSendPicTextCard(List loginNames, String title, String content, String pcUrl, String mobileUrl, String picUrl) { - String list = String.join(",", loginNames); - this.doSend("news", list, title, content, pcUrl, mobileUrl, picUrl); - } + @Override + public void massSendPicTextCard(List loginNames, String content, String pcUrl, String mobileUrl, String picUrl) { + this.massSendPicTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl, picUrl); + } - private void doSend(String sendType, - String receivers, - String title, - String content, - String pcUrl, - String mobileUrl, - String picUrl) { - if(!Globals.sso) { - log.error("【log】本地开发模式不允许调用消息接口"); - return; - } - if(!Globals.MyConfig.getBoolean("AppNotify", false)) { - log.error("【log】消息配置未开启"); - return; - } + @Override + public void massSendPicTextCard(List loginNames, String title, String content, String pcUrl, String mobileUrl, String picUrl) { + this.doSend("news", loginNames, title, content, pcUrl, mobileUrl, picUrl); + } - if (Lang.isEmpty(receivers)) { - log.error("【log】send fail by receivers is null"); - return; - } - try { - String token = smsTokenUtil.getToken(); - if (Lang.isEmpty(token)) { - log.error("【log】send fail by token is null"); - return; - } + private void doSend(String sendType, + List loginNames, + String title, + String content, + String pcUrl, + String mobileUrl, + String picUrl) { + if (!Globals.sso) { + log.error("【log】本地开发模式不允许调用消息接口"); + return; + } + if (!Globals.MyConfig.getBoolean("AppNotify", false)) { + log.error("【log】消息配置未开启"); + return; + } - Map params = new HashMap<>(); - params.put("appId", APP_ID); - params.put("sendId", ""); - params.put("sendType", Stream.of("WECHAT").toArray()); - params.put("messageTypeCode", TEMPLATE_ID); - params.put("promise", false); - params.put("importantIdentity", false); - params.put("toPersons", receivers); + String receivers = String.join(",", loginNames); + if (Lang.isEmpty(receivers)) { + log.error("【log】send fail by receivers is null"); + return; + } + try { + String token = smsTokenUtil.getToken(); + if (Lang.isEmpty(token)) { + log.error("【log】send fail by token is null"); + return; + } - Map dataParams = new HashMap<>(); - dataParams.put("title", title); - dataParams.put("paramValueJson", Map.of("content", content)); + Map params = new HashMap<>(); + params.put("appId", APP_ID); + params.put("sendId", ""); + params.put("sendType", Stream.of("WECHAT").toArray()); + params.put("messageTypeCode", TEMPLATE_ID); + params.put("promise", false); + params.put("importantIdentity", false); + params.put("toPersons", receivers); - if ("textCard".equals(sendType)) { - dataParams.put("url", pcUrl); - dataParams.put("mobileUrl", mobileUrl); - } - if ("news".equals(sendType)) { - dataParams.put("url", pcUrl); - dataParams.put("mobileUrl", mobileUrl); - dataParams.put("coverImageUrl", picUrl); - } - params.put("data", dataParams); + Map dataParams = new HashMap<>(); + dataParams.put("title", title); + dataParams.put("paramValueJson", Map.of("content", content)); - log.info("【log】发送消息通知,请求参数:{}", Json.toJson(params)); - String body = HttpUtil.createPost(SEND_MSG_URL) - .header("Authorization", token) - .header("Content-Type", "application/json") - .body(Json.toJson(params)).execute().body(); - JSONObject resultJsonBody = JSONUtil.parseObj(body); - log.info("【log】发送消息通知,接口响应数据:{}", body); + if ("textCard".equals(sendType)) { + dataParams.put("url", pcUrl); + dataParams.put("mobileUrl", mobileUrl); + } + if ("news".equals(sendType)) { + dataParams.put("url", pcUrl); + dataParams.put("mobileUrl", mobileUrl); + dataParams.put("coverImageUrl", picUrl); + } + params.put("data", dataParams); - if (resultJsonBody.getInt("code") == 0) { - log.info("【log】发送消息通知成功"); - JSONObject data = resultJsonBody.getJSONObject("data"); - String sendId = data.getStr("sendId"); - System.out.println(sendId); - } else { - log.info("【log】发送消息通知失败:{}", resultJsonBody.getStr("message")); - } - } catch (Exception e) { - log.error("【log】发送消息通知失败", e); - } - } + log.info("【log】发送消息通知,请求参数:{}", Json.toJson(params)); + String body = HttpUtil.createPost(SEND_MSG_URL) + .header("Authorization", token) + .header("Content-Type", "application/json") + .body(Json.toJson(params)).execute().body(); + JSONObject resultJsonBody = JSONUtil.parseObj(body); + log.info("【log】发送消息通知,接口响应数据:{}", body); + + if (resultJsonBody.getInt("code") == 0) { + log.info("【log】发送消息通知成功"); + JSONObject data = resultJsonBody.getJSONObject("data"); + String sendId = data.getStr("sendId"); + System.out.println(sendId); + } else { + log.info("【log】发送消息通知失败:{}", resultJsonBody.getStr("message")); + } + } catch (Exception e) { + log.error("【log】发送消息通知失败", e); + } + } + + /** + * 消息发送 成功后记录消息信息 + * + * @param sendType + * @param loginNames + * @param title + * @param content + * @param pcUrl + * @param mobileUrl + * @param projectName + * @param type + * @param remark + */ + private void doSendAndMessageRecordByType(String sendType, List loginNames, String title, + String content, String pcUrl, String mobileUrl, String picUrl, String type, String projectName, String remark) { + if (!Globals.sso) { + log.error("【log】本地开发模式不允许调用消息接口"); + return; + } + if (!Globals.MyConfig.getBoolean("AppNotify", false)) { + log.error("【log】消息配置未开启"); + return; + } + + //消息推送记录 + long time = Times.getTS(); + String userId = SecurityUtil.getUserId(); + Sys_msg sysMsg = new Sys_msg(); + sysMsg.setType(type); + sysMsg.setTitle(projectName); + sysMsg.setNote(content); + sysMsg.setSendAt(time); + sysMsg.setCreatedBy(userId); + sysMsg.setCreatedAt(time); + sysMsg.setUpdatedBy(userId); + sysMsg.setUpdatedAt(time); + sysMsg.setDelFlag(false); + sysMsg.setSendType("show"); + List sysMsgUsersInsert = new ArrayList<>(); + + List> loginNameLists = chunkList(loginNames, 50); + for (List loginNameList : loginNameLists) { + String receivers = String.join(",", loginNameList); + if (Lang.isEmpty(receivers)) { + log.error("【log】send fail by receivers is null"); + return; + } + + List sysMsgUsers = loginNameList.stream().map(loginName -> { + Sys_msg_user sysMsgUser = new Sys_msg_user(); + sysMsgUser.setLoginname(loginName); + sysMsgUser.setReadAt(Times.getTS()); + sysMsgUser.setCreatedAt(time); + sysMsgUser.setCreatedBy(userId); + sysMsgUser.setUpdatedAt(time); + sysMsgUser.setUpdatedBy(userId); + sysMsgUser.setDelFlag(false); + return sysMsgUser; + }).collect(Collectors.toList()); + + try { + String token = smsTokenUtil.getToken(); + if (Lang.isEmpty(token)) { + log.error("【log】send fail by token is null"); + return; + } + + Map params = new HashMap<>(); + params.put("appId", APP_ID); + params.put("sendId", ""); + params.put("sendType", Stream.of("WECHAT").toArray()); + params.put("messageTypeCode", TEMPLATE_ID); + params.put("promise", false); + params.put("importantIdentity", false); + params.put("toPersons", receivers); + + Map dataParams = new HashMap<>(); + dataParams.put("title", title); + dataParams.put("paramValueJson", Map.of("content", content)); + + if ("textCard".equals(sendType)) { + dataParams.put("url", pcUrl); + dataParams.put("mobileUrl", mobileUrl); + } + if ("news".equals(sendType)) { + dataParams.put("url", pcUrl); + dataParams.put("mobileUrl", mobileUrl); + dataParams.put("coverImageUrl", picUrl); + } + params.put("data", dataParams); + + log.info("【log】发送消息通知,请求参数:{}", Json.toJson(params)); + String body = HttpUtil.createPost(SEND_MSG_URL) + .header("Authorization", token) + .header("Content-Type", "application/json") + .body(Json.toJson(params)).execute().body(); + JSONObject resultJsonBody = JSONUtil.parseObj(body); + log.info("【log】发送消息通知,接口响应数据:{}", body); + Integer codeStatus = resultJsonBody.getInt("code"); + + if (codeStatus == 0) { + log.info("【log】发送消息通知成功"); + for (Sys_msg_user sysMsgUser : sysMsgUsers) { + sysMsgUser.setBackStatus(codeStatus); + sysMsgUser.setBackText("发送成功"); + } + sysMsgUsersInsert.addAll(sysMsgUsers); + } else { + String message = resultJsonBody.getStr("message"); + for (Sys_msg_user sysMsgUser : sysMsgUsers) { + sysMsgUser.setBackStatus(codeStatus); + sysMsgUser.setBackText(message); + } + sysMsgUsersInsert.addAll(sysMsgUsers); + log.info("【log】发送消息通知失败:{}", message); + } + + } catch (Exception e) { + String message = "发送失败,接口异常:"+e.getMessage(); + for (Sys_msg_user sysMsgUser : sysMsgUsers) { + sysMsgUser.setBackStatus(500); + sysMsgUser.setBackText(message); + } + sysMsgUsersInsert.addAll(sysMsgUsers); + log.error("【log】发送消息通知失败", e); + } + } + //记录发送状态及消息 + Set loginNameSet = sysMsgUsersInsert.stream().map(Sys_msg_user::getLoginname).collect(Collectors.toSet()); + List viewUsers = dao.query(View_user.class, Cnd.where("loginname", "in", loginNameSet)); + for (Sys_msg_user sysMsgUser : sysMsgUsersInsert) { + String loginname = sysMsgUser.getLoginname(); + View_user viewUser = viewUsers.stream().filter(e -> e.getLoginname().equals(loginname)).findFirst().orElse(null); + if(ObjectUtil.isNotEmpty(viewUser)) { + sysMsgUser.setUserName(viewUser.getUsername()); + sysMsgUser.setUnitId(viewUser.getUnitId()); + sysMsgUser.setUnitName(viewUser.getUnitName()); + sysMsgUser.setUnionId(viewUser.getUnionId()); + sysMsgUser.setUnionName(viewUser.getUnionName()); + } + } + Sys_msg sys_msg = dao.insert(sysMsg); + for (Sys_msg_user sysMsgUser : sysMsgUsersInsert) { + sysMsgUser.setMsgId(sys_msg.getId()); + } + dao.insert(sysMsgUsersInsert); + } + + /** + * 不安全的集合 + * + * @param list 需要拆分的集合 + * @param chunkSize 以多少条数据进行拆分; 每个新集合多少条数据 + * @param + * @return + */ + public static List> chunkList(List list, int chunkSize) { + List> chunks = new CopyOnWriteArrayList<>(); + for (int i = 0; i < list.size(); i += chunkSize) { + chunks.add(list.subList(i, Math.min(i + chunkSize, list.size()))); + } + return chunks; + } } diff --git a/src/main/java/com/budwk/app/sys/models/Sys_msg.java b/src/main/java/com/budwk/app/sys/models/Sys_msg.java index a58497eb..0af53df6 100644 --- a/src/main/java/com/budwk/app/sys/models/Sys_msg.java +++ b/src/main/java/com/budwk/app/sys/models/Sys_msg.java @@ -9,6 +9,7 @@ import org.nutz.dao.interceptor.annotation.PrevInsert; import javax.validation.constraints.NotBlank; import java.io.Serializable; +import java.util.Date; import java.util.List; @@ -72,4 +73,9 @@ public class Sys_msg extends BaseModel implements Serializable { @ColDefine(type = ColType.VARCHAR, width = 10) private String sendType; + @Column + @Comment("备注") + @ColDefine(type = ColType.TEXT) + private String remarks; + } diff --git a/src/main/java/com/budwk/app/sys/models/Sys_msg_user.java b/src/main/java/com/budwk/app/sys/models/Sys_msg_user.java index 4bfde74a..b4838184 100644 --- a/src/main/java/com/budwk/app/sys/models/Sys_msg_user.java +++ b/src/main/java/com/budwk/app/sys/models/Sys_msg_user.java @@ -74,6 +74,11 @@ public class Sys_msg_user extends BaseModel implements Serializable { @One(field = "msgId") private Sys_msg msg; + @Column + @Comment("发送状态") + @ColDefine(type = ColType.INT) + private Integer backStatus; + @Column @Comment("反馈内容") @ColDefine(type = ColType.VARCHAR, width = 500) diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupSingleController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupSingleController.java index de3ad919..b507d624 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupSingleController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupSingleController.java @@ -447,7 +447,10 @@ public class HealthCheckupSingleController { smsService.massSendTextCard(loginNameList, smsMessage, "#", - Globals.AppDomain); + Globals.AppDomain, + "healthCheckup", + project.getName(), + "未体检人员消息提醒"); return Result.success("提醒成功"); } else { return Result.success("不存在未体检人员");