提交 5d51c24b 作者: 洪东保

每两小时推送今日会议纪要统计

父级 3f9283a4
package com.cmeeting.config;
import com.cmeeting.vo.StatisticsEmailPush;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@ConfigurationProperties(prefix = "statistics.email-push")
@Getter
@Setter
public class StatisticsEmailPushProperties {
private List<StatisticsEmailPush.ToEmail> toEmails;
}
package com.cmeeting.controller; package com.cmeeting.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cmeeting.ad.entity.RobotSecurityUser; import com.cmeeting.ad.entity.RobotSecurityUser;
import com.cmeeting.ad.util.SecurityUtil; import com.cmeeting.ad.util.SecurityUtil;
import com.cmeeting.config.StatisticsEmailPushProperties;
import com.cmeeting.email.EmailSender; import com.cmeeting.email.EmailSender;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper; import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
import com.cmeeting.mapper.primary.UserIdMapper; import com.cmeeting.mapper.primary.UserIdMapper;
...@@ -17,17 +19,20 @@ import com.cmeeting.util.R; ...@@ -17,17 +19,20 @@ import com.cmeeting.util.R;
import com.cmeeting.vo.EmailPush; import com.cmeeting.vo.EmailPush;
import com.cmeeting.vo.EmailStatisticsVo; import com.cmeeting.vo.EmailStatisticsVo;
import com.cmeeting.vo.MeetingInfoVO; import com.cmeeting.vo.MeetingInfoVO;
import com.cmeeting.vo.StatisticsEmailPush;
import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.XWPFTemplate;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
...@@ -35,6 +40,11 @@ import javax.servlet.http.HttpServletResponse; ...@@ -35,6 +40,11 @@ import javax.servlet.http.HttpServletResponse;
import java.io.*; import java.io.*;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
...@@ -320,7 +330,61 @@ public class MeetingInfoController { ...@@ -320,7 +330,61 @@ public class MeetingInfoController {
@PostMapping("/statisticsByDept") @PostMapping("/statisticsByDept")
public void statisticsByDept(@RequestBody EmailStatisticsVo vo, HttpServletResponse response) { public void statisticsByDept(@RequestBody EmailStatisticsVo vo, HttpServletResponse response) throws IOException {
meetingInfoService.statisticsEmail(vo.getStartTime(), vo.getEndTime(), response); String title = String.format("会议纪要推送统计表_%s-%s", DateUtil.format(vo.getStartTime(), "yyyyMMdd"), DateUtil.format(vo.getEndTime(), "yyyyMMdd"));
String fileName = String.format("%s.xlsx", title);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf8"));
meetingInfoService.statisticsEmail(title, vo.getStartTime(), vo.getEndTime(), response.getOutputStream());
} }
@Resource
private StatisticsEmailPushProperties statisticsEmailPushProperties;
@Value(value = "${tencent.base-save-path}")
private String savePath;
/**
* 每天两小时发送会议统计邮件测试接口
*/
@GetMapping("/emailStatisticsPushTest")
public void emailStatisticsPush() {
List<StatisticsEmailPush.Attachment> attachments = new ArrayList<>();
String subject = "Cmeeting会议助手-会议纪要推送记录分析-" + new SimpleDateFormat("yyyyMMdd").format(new Date());
String content;
if (CollUtil.isEmpty(statisticsEmailPushProperties.getToEmails())) {
log.error("收件人为空!");
return;
}
File file = new File(savePath + subject + ".xlsx");
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
boolean b = meetingInfoService.statisticsEmail(subject, simpleDateFormat1.parse(simpleDateFormat.format(date) + " 00:00:00"),
simpleDateFormat1.parse(simpleDateFormat.format(date) + " 23:59:59"), new FileOutputStream(file));
if (b) {
content = "<p data-olk-copy-source=\\\"MessageBody\\\">Dear all:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;附件为今天Cmeeting会议纪要生成和发送情况,烦请查收。</p>";
StatisticsEmailPush.Attachment attachment = new StatisticsEmailPush.Attachment();
attachment.setName(subject);
attachment.setBytes(IOUtils.toByteArray(Files.newInputStream(file.toPath())));
attachments.add(attachment);
} else {
content = "<p data-olk-copy-source=\\\"MessageBody\\\">Dear all:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;今天到目前为止没有会议。</p>";
}
StatisticsEmailPush emailPushBuilder = StatisticsEmailPush.builder()
.toEmails(statisticsEmailPushProperties.getToEmails())
.attachments(attachments)
.subject(subject)
.content(content)
.build();
emailSender.emailStatisticsPush(emailPushBuilder);
} catch (IOException | ParseException e) {
throw new RuntimeException(e);
} finally {
file.delete();
}
}
} }
...@@ -10,6 +10,7 @@ import com.cmeeting.exception.RobotBaseException; ...@@ -10,6 +10,7 @@ import com.cmeeting.exception.RobotBaseException;
import com.cmeeting.log.service.ProcessLogService; import com.cmeeting.log.service.ProcessLogService;
import com.cmeeting.util.RedisUtils; import com.cmeeting.util.RedisUtils;
import com.cmeeting.vo.EmailPush; import com.cmeeting.vo.EmailPush;
import com.cmeeting.vo.StatisticsEmailPush;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider; import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.*; import com.microsoft.graph.models.*;
import com.microsoft.graph.models.Message; import com.microsoft.graph.models.Message;
...@@ -35,11 +36,8 @@ import java.nio.file.Files; ...@@ -35,11 +36,8 @@ import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Arrays; import java.util.*;
import java.util.Base64;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@Slf4j @Slf4j
...@@ -201,4 +199,87 @@ public class EmailSender { ...@@ -201,4 +199,87 @@ public class EmailSender {
return isSent; return isSent;
} }
public void emailStatisticsPush(StatisticsEmailPush emailPushBuilder) {
log.info("emailStatisticsPush start, sender -> {}", SENDER);
AtomicInteger retryCount = new AtomicInteger(0);
boolean isSent = false;
while (retryCount.intValue() < MAX_RETRY && !isSent){
try {
ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.clientId(CLIENT_ID)
.clientSecret(CLIENT_SECRET)
.tenantId(TENANT_ID)
.build();
try {
TokenRequestContext context = new TokenRequestContext().addScopes("https://graph.microsoft.com/.default");
AccessToken token = clientSecretCredential.getToken(context).block();
System.out.println(token != null ? token.getToken() : null);
} catch (Exception e) {
log.error("统计邮件获取访问令牌失败: {}", e.getMessage());
}
final TokenCredentialAuthProvider tokenCredAuthProvider = new TokenCredentialAuthProvider(Collections.singletonList("https://graph.microsoft.com/.default"), clientSecretCredential);
System.out.println("First Step Reached. ");
GraphServiceClient<Request> graphClient = GraphServiceClient.builder().authenticationProvider(tokenCredAuthProvider).buildClient();
com.microsoft.graph.models.Message message = new Message();
message.subject = emailPushBuilder.getSubject();
ItemBody body = new ItemBody();
body.contentType = BodyType.HTML;
body.content = emailPushBuilder.getContent();
message.body = body;
LinkedList<Recipient> toRecipientsList = new LinkedList<>();
for (StatisticsEmailPush.ToEmail toEmail : emailPushBuilder.getToEmails()) {
Recipient toRecipients = new Recipient();
EmailAddress emailAddress = new EmailAddress();
emailAddress.address = toEmail.getEmail();
emailAddress.name = toEmail.getUser();
toRecipients.emailAddress = emailAddress;
toRecipientsList.add(toRecipients);
}
message.toRecipients = toRecipientsList;
//构建附件
LinkedList<Attachment> attachmentsList = new LinkedList<>();
for (StatisticsEmailPush.Attachment attachment : emailPushBuilder.getAttachments()) {
FileAttachment attachments = new FileAttachment();
attachments.name = attachment.getName() + ".xlsx";
attachments.oDataType = "#microsoft.graph.fileAttachment";
attachments.contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
attachments.contentBytes = attachment.getBytes();
attachmentsList.add(attachments);
}
AttachmentCollectionResponse attachmentCollectionResponse = new AttachmentCollectionResponse();
attachmentCollectionResponse.value = attachmentsList;
message.attachments = new AttachmentCollectionPage(attachmentCollectionResponse, null);
//以指定用户邮箱发送邮件
graphClient.users(SENDER)
.sendMail(UserSendMailParameterSet.newBuilder().
withMessage(message).
withSaveToSentItems(true).build())
.buildRequest()
.post();
log.info("统计邮件已成功发送");
isSent = true;
} catch (Exception e) {
retryCount.getAndIncrement();
// 异常处理
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
if (retryCount.intValue() > MAX_RETRY) {
log.error("统计邮件发送达到最大重试次数");
throw new RuntimeException(e);
}
// 指数退避
try {
Thread.sleep((long) Math.pow(2, retryCount.intValue()) * 1000);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("统计邮件发送重试失败", ie);
}
}
}
}
} }
\ No newline at end of file
package com.cmeeting.job; package com.cmeeting.job;
import cn.hutool.core.collection.CollUtil;
import com.azure.core.credential.AccessToken;
import com.azure.core.credential.TokenRequestContext;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cmeeting.config.StatisticsEmailPushProperties;
import com.cmeeting.constant.MeetingState; import com.cmeeting.constant.MeetingState;
import com.cmeeting.dto.UserDTO; import com.cmeeting.dto.UserDTO;
import com.cmeeting.email.EmailSender;
import com.cmeeting.exception.RobotBaseException;
import com.cmeeting.mapper.primary.UserIdMapper; import com.cmeeting.mapper.primary.UserIdMapper;
import com.cmeeting.pojo.MeetingInfo; import com.cmeeting.pojo.MeetingInfo;
import com.cmeeting.pojo.UserId; import com.cmeeting.pojo.UserId;
import com.cmeeting.pojo.WeComUser; import com.cmeeting.pojo.WeComUser;
import com.cmeeting.service.*; import com.cmeeting.service.*;
import com.cmeeting.util.RedisUtils; import com.cmeeting.util.RedisUtils;
import com.cmeeting.vo.EmailPush;
import com.cmeeting.vo.StatisticsEmailPush;
import com.cmeeting.vo.TencentMeetingVO; import com.cmeeting.vo.TencentMeetingVO;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.*;
import com.microsoft.graph.requests.AttachmentCollectionPage;
import com.microsoft.graph.requests.AttachmentCollectionResponse;
import com.microsoft.graph.requests.GraphServiceClient;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
...@@ -19,11 +38,20 @@ import org.springframework.util.CollectionUtils; ...@@ -19,11 +38,20 @@ import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.*;
import java.io.File;
import java.nio.file.Files;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -46,6 +74,8 @@ public class CmeetingJob { ...@@ -46,6 +74,8 @@ public class CmeetingJob {
private Boolean isDev; private Boolean isDev;
@Resource @Resource
private RedisUtils redisUtils; private RedisUtils redisUtils;
@Resource
private EmailSender emailSender;
// @PostConstruct // @PostConstruct
public void weComUserInit(){ public void weComUserInit(){
...@@ -272,4 +302,53 @@ public class CmeetingJob { ...@@ -272,4 +302,53 @@ public class CmeetingJob {
redisUtils.del("Scheduled-email-retry"); redisUtils.del("Scheduled-email-retry");
} }
} }
@Resource
private StatisticsEmailPushProperties statisticsEmailPushProperties;
/**
* 每天两小时发送会议统计邮件
*/
@Value(value = "${tencent.base-save-path}")
private String savePath;
@Scheduled(cron = "0 0 0/2 * * ? ")
public void emailStatisticsPush() {
List<StatisticsEmailPush.Attachment> attachments = new ArrayList<>();
String subject = "Cmeeting会议助手-会议纪要推送记录分析-" + new SimpleDateFormat("yyyyMMdd").format(new Date());
String content;
if (CollUtil.isEmpty(statisticsEmailPushProperties.getToEmails())) {
log.error("收件人为空!");
return;
}
File file = new File(savePath + subject + ".xlsx");
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
boolean b = meetingInfoService.statisticsEmail(subject, simpleDateFormat1.parse(simpleDateFormat.format(date) + " 00:00:00"),
simpleDateFormat1.parse(simpleDateFormat.format(date) + " 23:59:59"), new FileOutputStream(file));
if (b) {
content = "<p data-olk-copy-source=\\\"MessageBody\\\">Dear all:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;附件为今天Cmeeting会议纪要生成和发送情况,烦请查收。</p>";
StatisticsEmailPush.Attachment attachment = new StatisticsEmailPush.Attachment();
attachment.setName(subject);
attachment.setBytes(IOUtils.toByteArray(Files.newInputStream(file.toPath())));
attachments.add(attachment);
} else {
content = "<p data-olk-copy-source=\\\"MessageBody\\\">Dear all:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;今天到目前为止没有会议。</p>";
}
StatisticsEmailPush emailPushBuilder = StatisticsEmailPush.builder()
.toEmails(statisticsEmailPushProperties.getToEmails())
.attachments(attachments)
.subject(subject)
.content(content)
.build();
emailSender.emailStatisticsPush(emailPushBuilder);
} catch (IOException | ParseException e) {
throw new RuntimeException(e);
} finally {
file.delete();
}
}
} }
...@@ -6,6 +6,7 @@ import com.cmeeting.pojo.MeetingInfo; ...@@ -6,6 +6,7 @@ import com.cmeeting.pojo.MeetingInfo;
import com.cmeeting.vo.MeetingInfoVO; import com.cmeeting.vo.MeetingInfoVO;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.Date; import java.util.Date;
public interface MeetingInfoService extends IService<MeetingInfo> { public interface MeetingInfoService extends IService<MeetingInfo> {
...@@ -19,6 +20,6 @@ public interface MeetingInfoService extends IService<MeetingInfo> { ...@@ -19,6 +20,6 @@ public interface MeetingInfoService extends IService<MeetingInfo> {
* 统计邮件推送情况 * 统计邮件推送情况
*/ */
void statisticsEmail(Integer type, Date startTime, Date endTime, HttpServletResponse response); void statisticsEmail(Integer type, Date startTime, Date endTime, HttpServletResponse response);
void statisticsEmail(Date startTime, Date endTime, HttpServletResponse response); boolean statisticsEmail(String title, Date startTime, Date endTime, OutputStream outputStream);
} }
...@@ -24,6 +24,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; ...@@ -24,6 +24,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.ad.entity.RobotSecurityUser; import com.cmeeting.ad.entity.RobotSecurityUser;
import com.cmeeting.ad.util.SecurityUtil; import com.cmeeting.ad.util.SecurityUtil;
import com.cmeeting.constant.MeetingState; import com.cmeeting.constant.MeetingState;
import com.cmeeting.exception.RobotBaseException;
import com.cmeeting.log.service.ProcessLogService; import com.cmeeting.log.service.ProcessLogService;
import com.cmeeting.mapper.primary.MeetingInfoMapper; import com.cmeeting.mapper.primary.MeetingInfoMapper;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper; import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
...@@ -558,10 +559,14 @@ public class MeetingInfoServiceImpl extends ServiceImpl<MeetingInfoMapper, Meeti ...@@ -558,10 +559,14 @@ public class MeetingInfoServiceImpl extends ServiceImpl<MeetingInfoMapper, Meeti
* 统计邮件推送情况 * 统计邮件推送情况
*/ */
@Override @Override
public void statisticsEmail(Date startTime, Date endTime, HttpServletResponse response) { public boolean statisticsEmail(String title, Date startTime, Date endTime, OutputStream outputStream) {
List<MeetingInfo> meetingInfoList = meetingInfoMapper.selectList(new LambdaQueryWrapper<MeetingInfo>() List<MeetingInfo> meetingInfoList = meetingInfoMapper.selectList(new LambdaQueryWrapper<MeetingInfo>()
.between(MeetingInfo::getStartTime, startTime, endTime)); .between(MeetingInfo::getStartTime, startTime, endTime));
log.info("会议总量: {}", meetingInfoList.size()); log.info("会议总量: {}", meetingInfoList.size());
if (meetingInfoList.size() == 0) {
log.info("时间段内没有会议");
return false;
}
// 查询工号以及部门 // 查询工号以及部门
List<String> uids = meetingInfoList.stream().map(MeetingInfo::getHostUid).distinct().collect(Collectors.toList()); List<String> uids = meetingInfoList.stream().map(MeetingInfo::getHostUid).distinct().collect(Collectors.toList());
...@@ -660,17 +665,8 @@ public class MeetingInfoServiceImpl extends ServiceImpl<MeetingInfoMapper, Meeti ...@@ -660,17 +665,8 @@ public class MeetingInfoServiceImpl extends ServiceImpl<MeetingInfoMapper, Meeti
mapList.add(totalMap); mapList.add(totalMap);
// 导出 // 导出
OutputStream outputStream = null;
ExcelWriter writer = ExcelUtil.getWriter(true); ExcelWriter writer = ExcelUtil.getWriter(true);
try { try {
String title = String.format("会议纪要推送统计表_%s-%s", DateUtil.format(startTime, "yyyyMMdd"), DateUtil.format(endTime, "yyyyMMdd"));
outputStream = response.getOutputStream();
String fileName = String.format("%s.xlsx", title);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf8"));
writer.addHeaderAlias("host", "部门"); writer.addHeaderAlias("host", "部门");
writer.addHeaderAlias("totalNum", "总会议"); writer.addHeaderAlias("totalNum", "总会议");
writer.addHeaderAlias("avaliableNum", "有效会议"); writer.addHeaderAlias("avaliableNum", "有效会议");
...@@ -692,5 +688,6 @@ public class MeetingInfoServiceImpl extends ServiceImpl<MeetingInfoMapper, Meeti ...@@ -692,5 +688,6 @@ public class MeetingInfoServiceImpl extends ServiceImpl<MeetingInfoMapper, Meeti
writer.close(); writer.close();
IoUtil.close(outputStream); IoUtil.close(outputStream);
} }
return true;
} }
} }
package com.cmeeting.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
;
/**
* 会议纪要模板展示层
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class StatisticsEmailPush {
private List<ToEmail> toEmails;
private String subject;
private String content;
/**
* 附件
*/
private List<Attachment> attachments;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class ToEmail {
private String user;
private String email;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class Attachment {
private String name;
private byte[] bytes;
}
}
\ No newline at end of file
...@@ -170,4 +170,11 @@ jasypt: ...@@ -170,4 +170,11 @@ jasypt:
prefix: ENC( prefix: ENC(
suffix: ) suffix: )
removeMenus:
isDev: true isDev: true
statistics:
email-push:
toEmails:
- user:
email: hongdongbao@chatbot.cn
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论