Browse Source

公众号通知消息

master
zhizhi wu 5 years ago
parent
commit
823e75f29b
  1. 4
      tall/src/main/java/com/ccsens/tall/aspect/RobotAspect.java
  2. 5
      tall/src/main/java/com/ccsens/tall/service/AsyncService.java
  3. 4
      tall/src/main/java/com/ccsens/tall/service/IAsyncService.java
  4. 3
      tall/src/main/java/com/ccsens/tall/service/IProjectMessageService.java
  5. 149
      tall/src/main/java/com/ccsens/tall/service/ProjectMessageService.java
  6. 20
      tall/src/main/java/com/ccsens/tall/service/RobotService.java
  7. 2
      tall/src/main/java/com/ccsens/tall/service/TaskSubTimeService.java
  8. 15
      tall/src/main/java/com/ccsens/tall/util/RobotUtil.java
  9. 169
      tall/src/main/java/com/ccsens/tall/util/WxTemplateUtil.java
  10. 21
      tall/src/main/java/com/ccsens/tall/web/DebugController.java
  11. 2
      tall/src/main/resources/application-dev.yml
  12. 4
      tall/src/main/resources/application-prod.yml
  13. 4
      tall/src/main/resources/application-test.yml
  14. 2
      tall/src/main/resources/mapper_dao/SysAuthDao.xml
  15. 6
      util/src/main/java/com/ccsens/util/PropUtil.java
  16. 10
      util/src/main/java/com/ccsens/util/WebConstant.java
  17. 5
      util/src/main/java/com/ccsens/util/WechatUtil.java
  18. 62
      util/src/main/java/com/ccsens/util/wx/WxGzhUtil.java
  19. 70
      util/src/main/java/com/ccsens/util/wx/WxTemplateMessage.java

4
tall/src/main/java/com/ccsens/tall/aspect/RobotAspect.java

@ -5,6 +5,7 @@ import com.ccsens.tall.service.IAsyncService;
import com.ccsens.tall.service.IRobotService; import com.ccsens.tall.service.IRobotService;
import com.ccsens.tall.util.RobotUtil; import com.ccsens.tall.util.RobotUtil;
import com.ccsens.util.annotation.OperateType; import com.ccsens.util.annotation.OperateType;
import com.ccsens.util.wx.WxTemplateMessage;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
@ -44,10 +45,11 @@ public class RobotAspect {
//2.获取发送参数 //2.获取发送参数
RobotUtil.Message message = RobotUtil.getRobotMessage(); RobotUtil.Message message = RobotUtil.getRobotMessage();
MessageVo.Inform inform = RobotUtil.getInform(); MessageVo.Inform inform = RobotUtil.getInform();
WxTemplateMessage wxTemplate = RobotUtil.getWxTemplate();
// 3.机器人通知 // 3.机器人通知
asyncService.sendRobotMessage(operateType,message); asyncService.sendRobotMessage(operateType,message);
// 4.ws和公众号通知 // 4.ws和公众号通知
asyncService.sendMessage(operateType, inform); asyncService.sendMessage(operateType, inform, wxTemplate);
//删除线程 //删除线程
RobotUtil.delRobotMessage(); RobotUtil.delRobotMessage();
RobotUtil.delInform(); RobotUtil.delInform();

5
tall/src/main/java/com/ccsens/tall/service/AsyncService.java

@ -3,6 +3,7 @@ package com.ccsens.tall.service;
import com.ccsens.tall.bean.vo.MessageVo; import com.ccsens.tall.bean.vo.MessageVo;
import com.ccsens.tall.util.RobotUtil; import com.ccsens.tall.util.RobotUtil;
import com.ccsens.util.annotation.OperateType; import com.ccsens.util.annotation.OperateType;
import com.ccsens.util.wx.WxTemplateMessage;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
@ -30,7 +31,7 @@ public class AsyncService implements IAsyncService{
} }
@Override @Override
public void sendMessage(OperateType operateType, MessageVo.Inform inform) throws JsonProcessingException { public void sendMessage(OperateType operateType, MessageVo.Inform inform, WxTemplateMessage wxTemplate) throws JsonProcessingException {
projectMessageService.sendProjectMessage(operateType, inform); projectMessageService.sendProjectMessage(operateType, inform, wxTemplate);
} }
} }

4
tall/src/main/java/com/ccsens/tall/service/IAsyncService.java

@ -3,6 +3,7 @@ package com.ccsens.tall.service;
import com.ccsens.tall.bean.vo.MessageVo; import com.ccsens.tall.bean.vo.MessageVo;
import com.ccsens.tall.util.RobotUtil; import com.ccsens.tall.util.RobotUtil;
import com.ccsens.util.annotation.OperateType; import com.ccsens.util.annotation.OperateType;
import com.ccsens.util.wx.WxTemplateMessage;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
/** /**
@ -15,8 +16,9 @@ public interface IAsyncService {
* 消息发送ws,公众号 * 消息发送ws,公众号
* @param operateType * @param operateType
* @param inform * @param inform
* @param wxTemplate
*/ */
void sendMessage(OperateType operateType, MessageVo.Inform inform) throws JsonProcessingException; void sendMessage(OperateType operateType, MessageVo.Inform inform, WxTemplateMessage wxTemplate) throws JsonProcessingException;
} }

3
tall/src/main/java/com/ccsens/tall/service/IProjectMessageService.java

@ -5,6 +5,7 @@ import com.ccsens.tall.bean.vo.MessageVo;
import com.ccsens.tall.bean.vo.ProjectMessageVo; import com.ccsens.tall.bean.vo.ProjectMessageVo;
import com.ccsens.util.CodeEnum; import com.ccsens.util.CodeEnum;
import com.ccsens.util.annotation.OperateType; import com.ccsens.util.annotation.OperateType;
import com.ccsens.util.wx.WxTemplateMessage;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@ -20,7 +21,7 @@ public interface IProjectMessageService {
* @param operateType * @param operateType
* @param inform * @param inform
*/ */
void sendProjectMessage(OperateType operateType, MessageVo.Inform inform) throws JsonProcessingException; void sendProjectMessage(OperateType operateType, MessageVo.Inform inform, WxTemplateMessage wxMessage) throws JsonProcessingException;
/** /**
* 查询未读消息数 * 查询未读消息数

149
tall/src/main/java/com/ccsens/tall/service/ProjectMessageService.java

@ -18,19 +18,21 @@ import com.ccsens.tall.persist.dao.SysAuthDao;
import com.ccsens.tall.persist.dao.SysMessageSendDao; import com.ccsens.tall.persist.dao.SysMessageSendDao;
import com.ccsens.tall.persist.dao.SysOperationDao; import com.ccsens.tall.persist.dao.SysOperationDao;
import com.ccsens.tall.persist.mapper.SysOperationMessageMapper; import com.ccsens.tall.persist.mapper.SysOperationMessageMapper;
import com.ccsens.util.CodeEnum; import com.ccsens.tall.util.RobotUtil;
import com.ccsens.util.JacksonUtil; import com.ccsens.tall.util.WxTemplateUtil;
import com.ccsens.util.TransactionUtil; import com.ccsens.util.*;
import com.ccsens.util.WebConstant;
import com.ccsens.util.annotation.OperateType; import com.ccsens.util.annotation.OperateType;
import com.ccsens.util.bean.message.common.InMessage; import com.ccsens.util.bean.message.common.InMessage;
import com.ccsens.util.config.RabbitMQConfig; import com.ccsens.util.config.RabbitMQConfig;
import com.ccsens.util.exception.BaseException; import com.ccsens.util.exception.BaseException;
import com.ccsens.util.wx.WxGzhUtil;
import com.ccsens.util.wx.WxTemplateMessage;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate; import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionException; import org.springframework.transaction.TransactionException;
@ -39,6 +41,7 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -68,11 +71,11 @@ public class ProjectMessageService implements IProjectMessageService {
private AmqpTemplate rabbitTemplate; private AmqpTemplate rabbitTemplate;
@Resource @Resource
private Snowflake snowflake; private Snowflake snowflake;
@Resource // @Resource
private PlatformTransactionManager transactionManager; // private PlatformTransactionManager transactionManager;
@Override @Override
public void sendProjectMessage(OperateType operateType, MessageVo.Inform inform) throws JsonProcessingException { public void sendProjectMessage(OperateType operateType, MessageVo.Inform inform, WxTemplateMessage wxMessage) throws JsonProcessingException {
log.info("发送消息请求参数:类型:{},消息:{}", operateType, inform); log.info("发送消息请求参数:类型:{},消息:{}", operateType, inform);
if (operateType == null || inform == null) { if (operateType == null || inform == null) {
throw new BaseException(CodeEnum.PARAM_ERROR); throw new BaseException(CodeEnum.PARAM_ERROR);
@ -87,11 +90,20 @@ public class ProjectMessageService implements IProjectMessageService {
return; return;
} }
//保存消息记录 //保存消息记录
Long operationId = initMessage(operateType, inform, newMessages, userIds); Long operationId = initMessage(operateType, inform, newMessages);
//查询关注公众号的用户
List<UserVo.Oauth2WX> oauths = sysAuthDao.queryOauth2WX(userIds);
List<String> openids = new ArrayList<>();
List<Long> oauthUserIds = new ArrayList<>();
oauths.forEach(oauth2WX -> {
openids.add(oauth2WX.getOpenid());
oauthUserIds.add(oauth2WX.getUserId());
});
//mq-->ws //mq-->ws
// 操作发送 // 操作发送
// initMessageSend(userIds, operationId, WebConstant.Message.SEND_WS); initMessageSend(userIds, oauthUserIds, operationId);
// InMessage inMessage = new InMessage(); // InMessage inMessage = new InMessage();
// inMessage.setTos(InMessage.transTos(userIds)); // inMessage.setTos(InMessage.transTos(userIds));
// inMessage.setData(JSONObject.toJSONString(newMessages)); // inMessage.setData(JSONObject.toJSONString(newMessages));
@ -107,28 +119,52 @@ public class ProjectMessageService implements IProjectMessageService {
updateStatus(operationId, WebConstant.Message.SEND_WS); updateStatus(operationId, WebConstant.Message.SEND_WS);
rabbitTemplate.convertAndSend(RabbitMQConfig.RabbitMQ_QUEUE_NAME, rabbitTemplate.convertAndSend(RabbitMQConfig.RabbitMQ_QUEUE_NAME,
JacksonUtil.beanToJson(dto)); JacksonUtil.beanToJson(dto));
//TODO 公众号通知消息
//查询关注公众号的用户 if (CollectionUtil.isEmpty(openids)) {
List<UserVo.Oauth2WX> oauths = sysAuthDao.queryOauth2WX(userIds);
if (CollectionUtil.isEmpty(oauths)) {
log.info("项目{}下没有关注公众号的用户,未发送公众号关注", inform.getProjectId()); log.info("项目{}下没有关注公众号的用户,未发送公众号关注", inform.getProjectId());
return; return;
} }
List<String> openids = new ArrayList<>(); String template = getTemplate(newMessages);
List<Long> oauthUserIds = new ArrayList<>(); openids.clear();
oauths.forEach(oauth2WX -> { openids.add("oALvgw6K6iHbOf7IqyyLFTD_rIVc");
openids.add(oauth2WX.getOpenid()); openids.forEach(openid -> {
oauthUserIds.add(oauth2WX.getUserId()); WxTemplateMessage wxTemplateMessage = new WxTemplateMessage();
}); BeanUtils.copyProperties(wxMessage, wxTemplateMessage);
wxTemplateMessage.setTouser(openid);
initMessageSend(oauthUserIds, operationId, WebConstant.Message.SEND_WX_OFFICIAL); wxTemplateMessage.getData().setRemark(new WxTemplateMessage.TemplateSettings(template));
//TODO 公众号通知消息 String result = RestTemplateUtil.postBody(WebConstant.Wx.TEMPLATE_SEND, wxTemplateMessage);
log.info("发送模板返回结果:{}", result);
// JsonResponse response = JSONObject.parseObject(result, JsonResponse.class);
JsonResponse response = null;
try {
response = JacksonUtil.xmlToBean(result, JsonResponse.class);
} catch (IOException e) {
e.printStackTrace();
}
if (response.getCode().intValue() != CodeEnum.SUCCESS.getCode().intValue()) {
//TODO 报警
log.error("公众号通知失败{}", result);
}
});
//更新ws消息发送成功 //更新ws消息发送成功
updateStatus(operationId, WebConstant.Message.SEND_WX_OFFICIAL); updateStatus(operationId, WebConstant.Message.SEND_WX_OFFICIAL);
} }
/**
* 获取模板
* @param newMessages
* @return
*/
private String getTemplate(List<MessageVo.Message> newMessages) {
StringBuilder builder = new StringBuilder();
newMessages.forEach(message -> {
builder.append(message.getContent());
});
return builder.toString();
}
/** /**
* 更新记录为发送成功 * 更新记录为发送成功
* @param operationId * @param operationId
@ -148,11 +184,9 @@ public class ProjectMessageService implements IProjectMessageService {
* @param operateType * @param operateType
* @param inform * @param inform
* @param messages * @param messages
* @param userIds
* @return * @return
*/ */
private Long initMessage(OperateType operateType, MessageVo.Inform inform, List<MessageVo.Message> messages, private Long initMessage(OperateType operateType, MessageVo.Inform inform, List<MessageVo.Message> messages) {
List<Long> userIds) {
// 操作日志 // 操作日志
SysOperation operation = new SysOperation(); SysOperation operation = new SysOperation();
operation.setId(snowflake.nextId()); operation.setId(snowflake.nextId());
@ -183,36 +217,55 @@ public class ProjectMessageService implements IProjectMessageService {
/** /**
* 保存消息通知了谁 * 保存消息通知了谁
* @param userIds * @param userIds
* @param wxUserIds
* @param operationId * @param operationId
*/ */
private void initMessageSend(List<Long> userIds, Long operationId, byte sendType) { private void initMessageSend(List<Long> userIds, List<Long> wxUserIds, Long operationId) {
TransactionStatus transactionStatus = TransactionUtil.getTransactionStatus(transactionManager);
int length = userIds.size() -1; // 封装发送消息记录
try { List<SysMessageSend> sends = new ArrayList<>();
for (int i = 0; i <= length ; i++) { appendSends(sends, userIds, WebConstant.Message.SEND_WS, operationId);
// 封装对象 appendSends(sends, wxUserIds, WebConstant.Message.SEND_WX_OFFICIAL, operationId);
Long userId = userIds.get(i); if (CollectionUtil.isEmpty(sends)) {
SysMessageSend send = new SysMessageSend(); return;
send.setId(snowflake.nextId()); }
send.setOperationId(operationId); int length = userIds.size();
send.setReceiverId(userId); // TransactionStatus transactionStatus = TransactionUtil.getTransactionStatus(transactionManager);
send.setSendType(sendType); // 设置手动事务提交
// try {
for (int i = 0; i < length ; i++) {
SysMessageSend send = sends.get(i);
sysMessageSendDao.insertSelective(send); sysMessageSendDao.insertSelective(send);
log.info("消息发送:{}", send); log.info("消息发送:{}", send);
// 判断是否需要提交事务,并开启新事务 // 判断是否需要提交事务,并开启新事务
boolean needCommit = (i > 0 && (i+1)%100==0) || i == length; // boolean needCommit = (i > 0 && (i+1)%100==0) || i >= length - 1;
if (needCommit) { // if (needCommit) {
transactionManager.commit(transactionStatus); // transactionManager.commit(transactionStatus);
if (i<length) { // if (i<length-1) {
transactionStatus = TransactionUtil.getTransactionStatus(transactionManager); // transactionStatus = TransactionUtil.getTransactionStatus(transactionManager);
} // }
//
} // }
} }
} catch (TransactionException e) { // } catch (Exception e) {
log.error("保存消息发送时出现异常", e); // log.error("保存消息发送时出现异常", e);
transactionManager.rollback(transactionStatus); // transactionManager.rollback(transactionStatus);
// }
}
private void appendSends(List<SysMessageSend> sends, List<Long> userIds, Byte type, Long operationId) {
if (CollectionUtil.isEmpty(userIds)) {
return;
} }
userIds.forEach(userId -> {
SysMessageSend send = new SysMessageSend();
send.setId(snowflake.nextId());
send.setOperationId(operationId);
send.setReceiverId(userId);
send.setSendType(type);
sends.add(send);
});
} }
/** /**

20
tall/src/main/java/com/ccsens/tall/service/RobotService.java

@ -9,6 +9,7 @@ import com.ccsens.tall.bean.vo.TaskVo;
import com.ccsens.tall.persist.dao.*; import com.ccsens.tall.persist.dao.*;
import com.ccsens.tall.util.RobotUtil; import com.ccsens.tall.util.RobotUtil;
import com.ccsens.tall.util.TallConstant; import com.ccsens.tall.util.TallConstant;
import com.ccsens.tall.util.WxTemplateUtil;
import com.ccsens.util.CodeEnum; import com.ccsens.util.CodeEnum;
import com.ccsens.util.RedisUtil; import com.ccsens.util.RedisUtil;
import com.ccsens.util.WebConstant; import com.ccsens.util.WebConstant;
@ -163,9 +164,11 @@ public class RobotService implements IRobotService{
message.appendMentionedMobileList(memberPhone); message.appendMentionedMobileList(memberPhone);
} }
RobotUtil.setRobotMessage(message); RobotUtil.setRobotMessage(message);
// 添加消息通知 // 添加ws消息通知
MessageVo.Inform inform = MessageVo.finishTask(currentUserId, userName, projectId, projectName, isFinish, taskName); MessageVo.Inform inform = MessageVo.finishTask(currentUserId, userName, projectId, projectName, isFinish, taskName);
RobotUtil.setInform(inform); RobotUtil.setInform(inform);
// 添加wx消息通知
RobotUtil.setWxTemplate(WxTemplateUtil.getFinishTask(projectId, userName, isFinish, taskName));
} }
@Override @Override
@ -197,6 +200,8 @@ public class RobotService implements IRobotService{
// 添加消息通知 // 添加消息通知
MessageVo.Inform inform = MessageVo.addTask(currentUserId, userName, project.getId(), projectName, taskName, executorName); MessageVo.Inform inform = MessageVo.addTask(currentUserId, userName, project.getId(), projectName, taskName, executorName);
RobotUtil.setInform(inform); RobotUtil.setInform(inform);
// 添加wx消息通知
RobotUtil.setWxTemplate(WxTemplateUtil.getAddTask(project.getId(), userName, taskName));
} }
@Override @Override
@ -221,6 +226,8 @@ public class RobotService implements IRobotService{
MessageVo.Inform inform = MessageVo.deleteTask(currentUserId, userName, sysProject.getId(), projectName, taskDetail.getName()); MessageVo.Inform inform = MessageVo.deleteTask(currentUserId, userName, sysProject.getId(), projectName, taskDetail.getName());
RobotUtil.setInform(inform); RobotUtil.setInform(inform);
// 添加wx消息通知
RobotUtil.setWxTemplate(WxTemplateUtil.getDeleteTask(sysProject.getId(), userName, taskDetail.getName()));
} }
@Override @Override
@ -241,6 +248,8 @@ public class RobotService implements IRobotService{
MessageVo.Inform inform = MessageVo.changeTask(currentUserId, userName, normalTask.getProjectId(), normalTask.getProjectName(), normalTask.getName(), normalTask.getExecutorRoleName()); MessageVo.Inform inform = MessageVo.changeTask(currentUserId, userName, normalTask.getProjectId(), normalTask.getProjectName(), normalTask.getName(), normalTask.getExecutorRoleName());
RobotUtil.setInform(inform); RobotUtil.setInform(inform);
// 添加wx消息通知
RobotUtil.setWxTemplate(WxTemplateUtil.getChangeTask(normalTask.getProjectId(), userName, normalTask.getName()));
} }
@ -276,6 +285,9 @@ public class RobotService implements IRobotService{
// 添加消息通知 // 添加消息通知
MessageVo.Inform inform = MessageVo.addDeliver(currentUserId, userName, taskDetail.getProjectId(), projectName, taskDetail.getName(),deliverName); MessageVo.Inform inform = MessageVo.addDeliver(currentUserId, userName, taskDetail.getProjectId(), projectName, taskDetail.getName(),deliverName);
RobotUtil.setInform(inform); RobotUtil.setInform(inform);
// 添加wx消息通知
RobotUtil.setWxTemplate(WxTemplateUtil.getAddDeliver(taskDetail.getProjectId(), userName, deliverName));
} }
@Override @Override
@ -310,6 +322,8 @@ public class RobotService implements IRobotService{
MessageVo.Inform inform = MessageVo.deleteDeliver(currentUserId, userName, project.getId(), project.getName(), taskDetail.getName(), deliverName); MessageVo.Inform inform = MessageVo.deleteDeliver(currentUserId, userName, project.getId(), project.getName(), taskDetail.getName(), deliverName);
RobotUtil.setInform(inform); RobotUtil.setInform(inform);
// 添加wx消息通知
RobotUtil.setWxTemplate(WxTemplateUtil.getDeleteDeliver(taskDetail.getProjectId(), userName, deliverName));
} }
@Override @Override
@ -343,6 +357,8 @@ public class RobotService implements IRobotService{
MessageVo.Inform inform = MessageVo.checkDeliver(currentUserId, userName, project.getId(), project.getName(), task.getName(), uploadUserName, deliverName); MessageVo.Inform inform = MessageVo.checkDeliver(currentUserId, userName, project.getId(), project.getName(), task.getName(), uploadUserName, deliverName);
RobotUtil.setInform(inform); RobotUtil.setInform(inform);
// 添加wx消息通知
RobotUtil.setWxTemplate(WxTemplateUtil.getCheckDeliver(project.getId(), userName, deliverName));
} }
@Override @Override
@ -368,5 +384,7 @@ public class RobotService implements IRobotService{
MessageVo.Inform inform = MessageVo.addComment(userId, userName, project.getId(), project.getName(), proTaskDetail.getName()); MessageVo.Inform inform = MessageVo.addComment(userId, userName, project.getId(), project.getName(), proTaskDetail.getName());
RobotUtil.setInform(inform); RobotUtil.setInform(inform);
// 添加wx消息通知
RobotUtil.setWxTemplate(WxTemplateUtil.getAddComment(project.getId(), userName));
} }
} }

2
tall/src/main/java/com/ccsens/tall/service/TaskSubTimeService.java

@ -176,7 +176,7 @@ public class TaskSubTimeService implements ITaskSubTimeService {
//返回的任务详细信息 //返回的任务详细信息
TaskVo.NormalTask normalTask = taskDetailService.getTaskInfoByTaskId(currentUserId, taskDetail.getProjectId(), subTimeId.getId()); TaskVo.NormalTask normalTask = taskDetailService.getTaskInfoByTaskId(currentUserId, taskDetail.getProjectId(), subTimeId.getId());
//用智能助手发送消息 //用智能助手/ws/wx发送消息
robotService.finishTaskRobotSend(currentUserId, normalTask.getProjectId(), normalTask.getProjectName(), normalTask.getName(), normalTask.getExecutorRole(), completedStatus); robotService.finishTaskRobotSend(currentUserId, normalTask.getProjectId(), normalTask.getProjectName(), normalTask.getName(), normalTask.getExecutorRole(), completedStatus);
return normalTask; return normalTask;

15
tall/src/main/java/com/ccsens/tall/util/RobotUtil.java

@ -1,6 +1,7 @@
package com.ccsens.tall.util; package com.ccsens.tall.util;
import com.ccsens.tall.bean.vo.MessageVo; import com.ccsens.tall.bean.vo.MessageVo;
import com.ccsens.util.wx.WxTemplateMessage;
import lombok.Data; import lombok.Data;
import java.util.ArrayList; import java.util.ArrayList;
@ -13,6 +14,8 @@ public class RobotUtil {
private static final ThreadLocal<Message> robotThreadLocal = new ThreadLocal<Message>(); private static final ThreadLocal<Message> robotThreadLocal = new ThreadLocal<Message>();
/** 消息推送(ws/公众号) */ /** 消息推送(ws/公众号) */
private static final ThreadLocal<MessageVo.Inform> informThreadLocal = new ThreadLocal<MessageVo.Inform>(); private static final ThreadLocal<MessageVo.Inform> informThreadLocal = new ThreadLocal<MessageVo.Inform>();
private static final ThreadLocal<WxTemplateMessage> wxMessageThreadLocal = new ThreadLocal<>();
@Data @Data
public static class Message{ public static class Message{
@ -85,6 +88,18 @@ public class RobotUtil {
informThreadLocal.remove(); informThreadLocal.remove();
} }
public static WxTemplateMessage getWxTemplate() {
return wxMessageThreadLocal.get();
}
public static void setWxTemplate(WxTemplateMessage message) {
wxMessageThreadLocal.set(message);
}
public static void delWxTemplate() {
wxMessageThreadLocal.remove();
}
} }

169
tall/src/main/java/com/ccsens/tall/util/WxTemplateUtil.java

@ -0,0 +1,169 @@
package com.ccsens.tall.util;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.ccsens.util.WechatUtil;
import com.ccsens.util.wx.WxGzhUtil;
import com.ccsens.util.wx.WxTemplateMessage;
/**
* @description: 微信模板
* @author: whj
* @time: 2020/6/9 11:07
*/
public class WxTemplateUtil {
/**
* 设置小程序跳转
* @param projectId
* @return
*/
private static WxTemplateMessage getWxTemplateMessage(Long projectId) {
String url = String.format(WechatUtil.PROJECT_URL, projectId);
WxTemplateMessage.MiniProgram miniProgram = new WxTemplateMessage.MiniProgram(WechatUtil.appid,url);
WxTemplateMessage message = new WxTemplateMessage();
message.setMiniprogram(miniProgram);
return message;
}
/**
* 完成任务提醒(备注是在切面处统一加的)
* @param projectId
* @param userName
* @param operation
* @param taskName
* @return
*/
public static WxTemplateMessage getFinishTask(Long projectId, String userName, String operation, String taskName){
WxTemplateMessage message = getWxTemplateMessage(projectId);
message.setTemplate_id(WxGzhUtil.Template.TASK_FINISH.templateId);
WxTemplateMessage.TemplateData data = new WxTemplateMessage.TemplateData();
data.setFirst(new WxTemplateMessage.TemplateSettings(userName + operation + taskName));
data.setKeyword1(new WxTemplateMessage.TemplateSettings(taskName));
data.setKeyword2(new WxTemplateMessage.TemplateSettings(DateUtil.now()));
message.setData(data);
return message;
}
/**
* 添加任务(备注是在切面处统一加的)
* @param projectId
* @param userName
* @param taskName
* @return
*/
public static WxTemplateMessage getAddTask(Long projectId, String userName, String taskName) {
WxTemplateMessage message = getWxTemplateMessage(projectId);
message.setTemplate_id(WxGzhUtil.Template.TASK_ADD.templateId);
WxTemplateMessage.TemplateData data = new WxTemplateMessage.TemplateData();
data.setFirst(new WxTemplateMessage.TemplateSettings(StrUtil.format("{}添加了{}任务", userName, taskName)));
data.setKeyword1(new WxTemplateMessage.TemplateSettings(taskName));
data.setKeyword2(new WxTemplateMessage.TemplateSettings(DateUtil.now()));
message.setData(data);
return message;
}
/**
* 删除任务
* @param projectId
* @param userName
* @param taskName
* @return
*/
public static WxTemplateMessage getDeleteTask(Long projectId, String userName, String taskName) {
WxTemplateMessage message = getWxTemplateMessage(projectId);
message.setTemplate_id(WxGzhUtil.Template.TASK_DELETE.templateId);
WxTemplateMessage.TemplateData data = new WxTemplateMessage.TemplateData();
data.setFirst(new WxTemplateMessage.TemplateSettings(StrUtil.format("{}删除了{}任务", userName, taskName)));
data.setKeyword1(new WxTemplateMessage.TemplateSettings(taskName));
data.setKeyword2(new WxTemplateMessage.TemplateSettings(DateUtil.now()));
data.setKeyword3(new WxTemplateMessage.TemplateSettings(""));
message.setData(data);
return message;
}
/**
* 修改任务
* @param projectId
* @param userName
* @param taskName
* @return
*/
public static WxTemplateMessage getChangeTask(Long projectId, String userName, String taskName) {
WxTemplateMessage message = getAddTask(projectId, userName, taskName);
message.getData().setFirst(new WxTemplateMessage.TemplateSettings(StrUtil.format("{}修改了{}任务", userName, taskName)));
return message;
}
/**
* 上传交付物
* @param projectId
* @param userName
* @param deliverName
* @return
*/
public static WxTemplateMessage getAddDeliver(Long projectId, String userName, String deliverName) {
WxTemplateMessage message = getWxTemplateMessage(projectId);
message.setTemplate_id(WxGzhUtil.Template.TASK_PROGRESS.templateId);
WxTemplateMessage.TemplateData data = new WxTemplateMessage.TemplateData();
data.setFirst(new WxTemplateMessage.TemplateSettings(""));
data.setKeyword1(new WxTemplateMessage.TemplateSettings(userName + "上传了" + deliverName));
data.setKeyword2(new WxTemplateMessage.TemplateSettings("上传交付物"));
message.setData(data);
return message;
}
/**
* 删除交付物
* @param projectId
* @param userName
* @param deliverName
* @return
*/
public static WxTemplateMessage getDeleteDeliver(Long projectId, String userName, String deliverName) {
WxTemplateMessage message = getAddDeliver(projectId, userName, deliverName);
WxTemplateMessage.TemplateData data = message.getData();
data.setKeyword1(new WxTemplateMessage.TemplateSettings(userName + "删除了" + deliverName));
data.setKeyword2(new WxTemplateMessage.TemplateSettings("删除交付物"));
message.setData(data);
return message;
}
/**
* 检查交付物
* @param projectId
* @param userName
* @param deliverName
* @return
*/
public static WxTemplateMessage getCheckDeliver(Long projectId, String userName, String deliverName) {
WxTemplateMessage message = getAddDeliver(projectId, userName, deliverName);
WxTemplateMessage.TemplateData data = message.getData();
data.setKeyword1(new WxTemplateMessage.TemplateSettings(userName + "检查了" + deliverName));
data.setKeyword2(new WxTemplateMessage.TemplateSettings("检查交付物"));
message.setData(data);
return message;
}
/**
* 发表评论
* @param projectId
* @param userName
* @return
*/
public static WxTemplateMessage getAddComment(Long projectId, String userName) {
WxTemplateMessage message = getWxTemplateMessage(projectId);
message.setTemplate_id(WxGzhUtil.Template.COMMENT.templateId);
WxTemplateMessage.TemplateData data = new WxTemplateMessage.TemplateData();
data.setFirst(new WxTemplateMessage.TemplateSettings(userName + "进行了点评"));
data.setKeyword1(new WxTemplateMessage.TemplateSettings(userName));
data.setKeyword2(new WxTemplateMessage.TemplateSettings(DateUtil.now()));
message.setData(data);
return message;
}
}

21
tall/src/main/java/com/ccsens/tall/web/DebugController.java

@ -2,6 +2,7 @@ package com.ccsens.tall.web;
import com.ccsens.util.JacksonUtil; import com.ccsens.util.JacksonUtil;
import com.ccsens.util.JsonResponse; import com.ccsens.util.JsonResponse;
import com.ccsens.util.TransactionUtil;
import com.ccsens.util.bean.message.client.AuthMessage; import com.ccsens.util.bean.message.client.AuthMessage;
import com.ccsens.util.bean.message.common.InMessage; import com.ccsens.util.bean.message.common.InMessage;
import com.ccsens.util.bean.message.common.MessageConstant; import com.ccsens.util.bean.message.common.MessageConstant;
@ -13,10 +14,13 @@ import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.amqp.core.AmqpTemplate; import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -28,16 +32,31 @@ public class DebugController {
@Autowired @Autowired
private AmqpTemplate rabbitTemplate; private AmqpTemplate rabbitTemplate;
@Resource
private PlatformTransactionManager transactionManager;
@ApiOperation(value = "/测试",notes = "") @ApiOperation(value = "/测试",notes = "")
@ApiImplicitParams({ @ApiImplicitParams({
}) })
@RequestMapping(value="",method = RequestMethod.GET,produces = {"application/json;charset=UTF-8"}) @RequestMapping(value="",method = RequestMethod.GET,produces = {"application/json;charset=UTF-8"})
public JsonResponse getSmsCode(HttpServletRequest request) throws Exception { public JsonResponse getSmsCode(HttpServletRequest request) throws Exception {
commit();
commit();
return JsonResponse.newInstance().ok("测试"); return JsonResponse.newInstance().ok("测试");
} }
private void commit() {
TransactionStatus transactionStatus = TransactionUtil.getTransactionStatus(transactionManager);
for (int i = 0; i < 10; i++) {
transactionManager.commit(transactionStatus);
transactionStatus = TransactionUtil.getTransactionStatus(transactionManager);
}
}
@ApiOperation(value = "消息测试",notes = "") @ApiOperation(value = "消息测试",notes = "")
@ApiImplicitParams({ @ApiImplicitParams({

2
tall/src/main/resources/application-dev.yml

@ -30,4 +30,6 @@ spring:
swagger: swagger:
enable: true enable: true
notGatewayUrl: /home/staticrec/logo.png notGatewayUrl: /home/staticrec/logo.png
wx:
prefixUrl: https://test.tall.wiki/wxconfigurer-api/

4
tall/src/main/resources/application-prod.yml

@ -36,4 +36,6 @@ eureka:
ip-address: 192.144.182.42 ip-address: 192.144.182.42
gatewayUrl: https://www.tall.wiki/gateway/ gatewayUrl: https://www.tall.wiki/gateway/
notGatewayUrl: https://www.tall.wiki/ notGatewayUrl: https://www.tall.wiki/
wx:
prefixUrl: https://test.tall.wiki/wxconfigurer-api

4
tall/src/main/resources/application-test.yml

@ -35,4 +35,6 @@ eureka:
ip-address: 192.168.0.99 ip-address: 192.168.0.99
# ip-address: 49.233.89.188 # ip-address: 49.233.89.188
gatewayUrl: http://192.168.0.99/gateway/ gatewayUrl: http://192.168.0.99/gateway/
notGatewayUrl: http://192.168.0.99/ notGatewayUrl: http://192.168.0.99/
wx:
prefixUrl: https://test.tall.wiki/wxconfigurer-api

2
tall/src/main/resources/mapper_dao/SysAuthDao.xml

@ -5,7 +5,7 @@
<select id="queryOauth2WX" resultType="com.ccsens.tall.bean.vo.UserVo$Oauth2WX"> <select id="queryOauth2WX" resultType="com.ccsens.tall.bean.vo.UserVo$Oauth2WX">
select identifier as openid, user_id as userId select identifier as openid, user_id as userId
from t_sys_auth from t_sys_auth
where identify_type = 4 where identify_type = 9
and user_id in and user_id in
<foreach collection="list" open="(" close=")" separator="," item="item"> <foreach collection="list" open="(" close=")" separator="," item="item">
#{item} #{item}

6
util/src/main/java/com/ccsens/util/PropUtil.java

@ -19,6 +19,7 @@ public class PropUtil {
public static String gatewayUrl; public static String gatewayUrl;
public static String notGatewayUrl; public static String notGatewayUrl;
public static String qrCode; public static String qrCode;
public static String wxPrefix;
@Value("${gatewayUrl:}") @Value("${gatewayUrl:}")
public void setGatewayUrl(String gatewayUrl) { public void setGatewayUrl(String gatewayUrl) {
@ -53,5 +54,8 @@ public class PropUtil {
public void setContextPath(String contextPath) { public void setContextPath(String contextPath) {
PropUtil.contextPath = contextPath; PropUtil.contextPath = contextPath;
} }
@Value("${wx.prefixUrl:}")
public void setWxPrefix(String wxPrefix) {
PropUtil.wxPrefix = wxPrefix;
}
} }

10
util/src/main/java/com/ccsens/util/WebConstant.java

@ -32,6 +32,7 @@ public class WebConstant {
} }
} }
public static final class Message{ public static final class Message{
public static final byte TYPE_TEXT = 0; public static final byte TYPE_TEXT = 0;
public static final byte TYPE_LINK = 1; public static final byte TYPE_LINK = 1;
@ -54,6 +55,9 @@ public class WebConstant {
public static final class Wx { public static final class Wx {
public static final String ACCESS_TOKEN = "tall_wx_access_token"; public static final String ACCESS_TOKEN = "tall_wx_access_token";
public static final long EXPIRE_TIME = 1 * 60 * 60; public static final long EXPIRE_TIME = 1 * 60 * 60;
public static final String DOMAIN = PropUtil.wxPrefix;
public static final String TEMPLATE_SEND = DOMAIN + "template/send";
} }
/**注册来源*/ /**注册来源*/
@ -224,8 +228,10 @@ public class WebConstant {
public enum IDENTIFY_TYPE { public enum IDENTIFY_TYPE {
Wxmp(0,"微信小程序"), Phone(1,"电话") Wxmp(0,"微信小程序"), Phone(1,"电话")
, Email(2,"Email"), Account(3,"账号") , Email(2,"Email"), Account(3,"账号")
,OAUTH2_Wx(4,"微信公众号"),Wx_H5(5,"网页微信登陆") ,OAUTH2_Wx(4,"微信公众号网页授权登录"),Wx_H5(5,"网页微信登陆")
,OAUTH2_WeiBo(6,"微博"),WxEnterprise(7, "企业微信"),; ,OAUTH2_WeiBo(6,"微博"),WxEnterprise(7, "企业微信"),
OFFICIAL_ACCOUNT_WX(9,"微信公众号登录");
// 钉钉是8
public int value; public int value;
public String phase; public String phase;

5
util/src/main/java/com/ccsens/util/WechatUtil.java

@ -136,11 +136,12 @@ public class WechatUtil {
private static final String URL_PAY_TO_USR_BANK private static final String URL_PAY_TO_USR_BANK
= "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank"; = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
private static final String appid = "wx356e01c7eb01d55d"; /**Anyring appid*/
public static final String appid = "wx356e01c7eb01d55d";
private static final String secret = "83149f3e151d9532f1d2eb76ca10722b"; private static final String secret = "83149f3e151d9532f1d2eb76ca10722b";
private static final String mchid = "1513955071"; private static final String mchid = "1513955071";
private static final String key = "5a689a2d6b8c4ff499c23d998fde0941"; //商户平台key private static final String key = "5a689a2d6b8c4ff499c23d998fde0941"; //商户平台key
public static final String PROJECT_URL = "pages/project/project?projectId=%1$s&scene=2001";
/** /**
* 小程序登陆根据code获取用户信息(openid,sessionKey,) * 小程序登陆根据code获取用户信息(openid,sessionKey,)
* @param code * @param code

62
util/src/main/java/com/ccsens/util/wx/WxGzhUtil.java

@ -5,6 +5,8 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil; import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.ccsens.util.DateUtil; import com.ccsens.util.DateUtil;
import com.ccsens.util.JacksonUtil; import com.ccsens.util.JacksonUtil;
import com.ccsens.util.RedisUtil; import com.ccsens.util.RedisUtil;
@ -14,6 +16,7 @@ import com.ccsens.util.exception.BaseException;
import com.ccsens.util.exception.BusinessException; import com.ccsens.util.exception.BusinessException;
import com.ccsens.util.exception.WxException; import com.ccsens.util.exception.WxException;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.Getter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -77,6 +80,8 @@ public class WxGzhUtil {
= "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%1$s&secret=%2$s&code=%3$s&grant_type=authorization_code"; = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%1$s&secret=%2$s&code=%3$s&grant_type=authorization_code";
private static final String URL_GET_OAUTH2_USERINFO private static final String URL_GET_OAUTH2_USERINFO
= "https://api.weixin.qq.com/sns/userinfo?access_token=%1$s&openid=%2$s"; = "https://api.weixin.qq.com/sns/userinfo?access_token=%1$s&openid=%2$s";
public static final String MESSAGE_TEMPLATE_SEND = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%1$s";
private static final String APPID = "wx7af1bf1e14facf82"; private static final String APPID = "wx7af1bf1e14facf82";
private static final String SECRET = "a6613fae11b497639c0224b820aaf6d9"; private static final String SECRET = "a6613fae11b497639c0224b820aaf6d9";
@ -92,6 +97,37 @@ public class WxGzhUtil {
private static final String MCHID = ""; private static final String MCHID = "";
private static final String KEY = ""; private static final String KEY = "";
public enum Template{
TASK_FINISH("OtFNgGj9Eiy3MuWO6j3Mb-An4LsVnIEBQCn1ZBSAXR8","工作完成通知","{{first.DATA}}工作内容:{{keyword1.DATA}}创建时间:{{keyword2.DATA}}{{remark.DATA}}"),
TASK_ADD("Tj0n5-aLvrrAksbGH5A1h-Dx44Z3c9u6cu7WZK5StEQ","工作分配通知", "{{first.DATA}}工作内容:{{keyword1.DATA}}创建时间:{{keyword2.DATA}}{{remark.DATA}}"),
TASK_DELETE("0qi0qqFyNQL0UChGlXLx92EtsBDhTLMINnt0akK1pyM","工作取消通知", "{{first.DATA}}工作内容:{{keyword1.DATA}}工作时间:{{keyword2.DATA}}详情:{{keyword3.DATA}}{{remark.DATA}}"),
TASK_PROGRESS("NeBLAEbPRFV4O5gkFeHTgPmwcpIUaMY_XkmhjLZ9v_4","工作进度通知", "{{first.DATA}}工作内容:{{keyword1.DATA}}当前状态:{{keyword2.DATA}}{{remark.DATA}}"),
COMMENT("NeBLAEbPRFV4O5gkFeHTgPmwcpIUaMY_XkmhjLZ9v_4","工作进度通知", "{{first.DATA}}工作内容:{{keyword1.DATA}}当前状态:{{keyword2.DATA}}{{remark.DATA}}"),
;
public String templateId;
public String title;
public String content;
Template(String templateId, String title, String content) {
this.templateId = templateId;
this.title = title;
this.content = content;
}
}
public static final class Field{
public static final int SUCCESS_CODE = 0;
public static final String ERROR_CODE = "errcode";
public static final String ERROR_MSG = "errmsg";
public static final String TOTAL = "total";
public static final String COUNT = "count";
public static final String DATA = "data";
public static final String OPENID = "openid";
public static final String NEXT_OPENID = "next_openid";
public static final String EVENT = "Event";
}
private static String appId(WebConstant.IDENTIFY_TYPE identifyType){ private static String appId(WebConstant.IDENTIFY_TYPE identifyType){
switch (identifyType){ switch (identifyType){
case Wx_H5: case Wx_H5:
@ -316,4 +352,30 @@ public class WxGzhUtil {
WxOauth2AccessToken wxOauth2AccessToken = getOauth2AccessToken(identifyType,code); WxOauth2AccessToken wxOauth2AccessToken = getOauth2AccessToken(identifyType,code);
return getOauth2UserInfo(wxOauth2AccessToken.getAccessToken(),wxOauth2AccessToken.getOpenId()); return getOauth2UserInfo(wxOauth2AccessToken.getAccessToken(),wxOauth2AccessToken.getOpenId());
} }
public static void sendTemplate(WxTemplateMessage message) {
String url = String.format(MESSAGE_TEMPLATE_SEND,getAccessToken());
String response = HttpRequest.post(url).body(JSONObject.toJSONString(message)).execute().body();
pageResponseSuccess(response);
}
/**
* 判断结果是否正确 错误抛异常errcode!=0为错误
* @param response
*/
public static void pageResponseSuccess(String response) {
Console.log("返回结果:{}", response);
JSONObject result;
try {
if(StrUtil.isEmpty(response) || null == (result = JSONObject.parseObject(response))) {
throw new BusinessException(-1,"the response of HttpRequest is empty.");
}
} catch (JSONException e) {
throw new BusinessException(-1,e.getMessage());
}
if(result.getIntValue(Field.ERROR_CODE) != Field.SUCCESS_CODE){
throw new WxException(result.getInteger(Field.ERROR_CODE),result.getString(Field.ERROR_MSG));
}
}
} }

70
util/src/main/java/com/ccsens/util/wx/WxTemplateMessage.java

@ -0,0 +1,70 @@
package com.ccsens.util.wx;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
/**
* @description:
* @author: whj
* @time: 2020/6/9 9:59
*/
@ApiModel("微信模板消息")
@Data
public class WxTemplateMessage {
@NotNull
@ApiModelProperty("接收者openid")
private String touser;
@NotNull
@ApiModelProperty("模板ID")
private String template_id;
@ApiModelProperty("模板跳转链接(海外帐号没有跳转能力)")
private String url;
@ApiModelProperty("小程序")
private MiniProgram miniprogram;
@ApiModelProperty("模板数据")
private TemplateData data ;
@ApiModel("跳转小程序")
@Data
public static class MiniProgram{
@ApiModelProperty("所需跳转到的小程序appid(该小程序appid必须与发模板消息的公众号是绑定关联关系,暂不支持小游戏)")
private String appid;
@ApiModelProperty("所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar),要求该小程序已发布,暂不支持小游戏")
private String pagepath;
public MiniProgram(String appid, String pagepath) {
this.appid = appid;
this.pagepath = pagepath;
}
}
@Data
@ApiModel("模板数据")
public static class TemplateData{
private TemplateSettings first;
private TemplateSettings keyword1;
private TemplateSettings keyword2;
private TemplateSettings keyword3;
private TemplateSettings remark;
}
@Getter @Setter
@ApiModel("模板参数配置")
public static class TemplateSettings {
@ApiModelProperty("模板值")
private String value;
@ApiModelProperty("模板内容字体颜色,不填默认为黑色")
private String color;
public TemplateSettings(){}
public TemplateSettings(String value) {
this.value = value;
}
}
}
Loading…
Cancel
Save