提交 c8ea969a 作者: 洪东保

Merge branch 'old'

# Conflicts:
#	src/main/java/com/cmeeting/controller/MeetingInfoController.java
#	src/main/java/com/cmeeting/job/CmeetingJob.java
#	src/main/java/com/cmeeting/service/FileProcessProducer.java
#	src/main/java/com/cmeeting/service/SysUserSyncService.java
#	src/main/java/com/cmeeting/service/impl/MeetingInfoServiceImpl.java
#	src/main/java/com/cmeeting/service/impl/SysUserSyncServiceImpl.java
#	src/main/resources/application.yml
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.annotation.OperLog; import com.cmeeting.annotation.OperLog;
import com.cmeeting.config.StatisticsEmailPushProperties;
import com.cmeeting.email.EmailSender; import com.cmeeting.email.EmailSender;
import com.cmeeting.exception.RobotBaseException; import com.cmeeting.exception.RobotBaseException;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper; import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
...@@ -19,17 +21,20 @@ import com.cmeeting.util.R; ...@@ -19,17 +21,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;
...@@ -37,6 +42,11 @@ import javax.servlet.http.HttpServletResponse; ...@@ -37,6 +42,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;
...@@ -327,7 +337,66 @@ public class MeetingInfoController { ...@@ -327,7 +337,66 @@ public class MeetingInfoController {
@PostMapping("/statistics") @PostMapping("/statistics")
public void statisticsEmail(@RequestBody EmailStatisticsVo vo, HttpServletResponse response) { public void statisticsEmail(@RequestBody EmailStatisticsVo vo, HttpServletResponse response) {
meetingInfoService.statisticsEmail(vo.getType(), vo.getStartTime(), vo.getEndTime(), response); meetingInfoService.statisticsEmail(vo.getType(), vo.getStartTime(), vo.getEndTime(), response);
} }
@PostMapping("/statisticsByDept")
public void statisticsByDept(@RequestBody EmailStatisticsVo vo, HttpServletResponse response) throws IOException {
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();
}
}
} }
...@@ -13,6 +13,7 @@ import com.cmeeting.pojo.MeetEmailTemplate; ...@@ -13,6 +13,7 @@ import com.cmeeting.pojo.MeetEmailTemplate;
import com.cmeeting.service.MeetEmailTemplateService; import com.cmeeting.service.MeetEmailTemplateService;
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;
...@@ -38,11 +39,8 @@ import java.nio.file.Files; ...@@ -38,11 +39,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
...@@ -77,7 +75,7 @@ public class EmailSender { ...@@ -77,7 +75,7 @@ public class EmailSender {
* @param emailPushBuilder * @param emailPushBuilder
* @return * @return
*/ */
public boolean sendEmailWithAttachment(EmailPush emailPushBuilder) { public Boolean sendEmailWithAttachment(EmailPush emailPushBuilder) {
log.info("sendEmailWithAttachment start, sender -> {}", SENDER); log.info("sendEmailWithAttachment start, sender -> {}", SENDER);
if(!pushSwitch){ if(!pushSwitch){
...@@ -85,7 +83,7 @@ public class EmailSender { ...@@ -85,7 +83,7 @@ public class EmailSender {
return false; return false;
} }
AtomicInteger retryCount = new AtomicInteger(0); AtomicInteger retryCount = new AtomicInteger(0);
boolean isSent = false; Boolean isSent = false;
String toEmail = "test".equals(environment) ? testReceiver : emailPushBuilder.getToEmail(); String toEmail = "test".equals(environment) ? testReceiver : emailPushBuilder.getToEmail();
String subject = emailPushBuilder.getSubject(); String subject = emailPushBuilder.getSubject();
String meetingId = emailPushBuilder.getMeetingId(); String meetingId = emailPushBuilder.getMeetingId();
...@@ -108,7 +106,7 @@ public class EmailSender { ...@@ -108,7 +106,7 @@ public class EmailSender {
return false; return false;
} }
log.info("准备开始邮件推送..."); log.info("准备开始邮件推送...");
while (retryCount.intValue() < MAX_RETRY && !isSent){ while (retryCount.intValue() < MAX_RETRY && isSent != null && !isSent){
try { try {
ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder() ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.clientId(CLIENT_ID) .clientId(CLIENT_ID)
...@@ -145,7 +143,7 @@ public class EmailSender { ...@@ -145,7 +143,7 @@ public class EmailSender {
long expireTimestamp = ZonedDateTime.now().plusDays(2).toInstant().toEpochMilli(); long expireTimestamp = ZonedDateTime.now().plusDays(2).toInstant().toEpochMilli();
body.content = MessageFormat.format(email_content_template,meetingInstanceId,toUserCode,String.valueOf(expireTimestamp)); body.content = MessageFormat.format(email_content_template,meetingInstanceId,toUserCode,String.valueOf(expireTimestamp));
}else{ }else{
isSent = false; isSent = null;
processLogService.log(meetingId,subMeetingId,"【邮件推送异常】:邮件模板未设置"); processLogService.log(meetingId,subMeetingId,"【邮件推送异常】:邮件模板未设置");
throw new RobotBaseException("邮件模板未设置"); throw new RobotBaseException("邮件模板未设置");
} }
...@@ -207,4 +205,87 @@ public class EmailSender { ...@@ -207,4 +205,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.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.io.IoUtil;
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.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cmeeting.constant.MeetingState; import com.cmeeting.constant.MeetingState;
...@@ -10,6 +10,7 @@ import com.cmeeting.mapper.primary.MeetingInfoMapper; ...@@ -10,6 +10,7 @@ import com.cmeeting.mapper.primary.MeetingInfoMapper;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper; import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
import com.cmeeting.pojo.MeetingInfo; import com.cmeeting.pojo.MeetingInfo;
import com.cmeeting.pojo.MeetingRecordTemplate; import com.cmeeting.pojo.MeetingRecordTemplate;
import com.cmeeting.util.AESUtils;
import com.cmeeting.util.MinioUtils; import com.cmeeting.util.MinioUtils;
import com.cmeeting.util.RedisUtils; import com.cmeeting.util.RedisUtils;
import com.cmeeting.vo.EmailPush; import com.cmeeting.vo.EmailPush;
...@@ -20,14 +21,10 @@ import lombok.Data; ...@@ -20,14 +21,10 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
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;
...@@ -52,21 +49,27 @@ public class EmailPushTask { ...@@ -52,21 +49,27 @@ public class EmailPushTask {
private EmailSender emailSender; private EmailSender emailSender;
private MeetingRecordTemplateMapper meetingRecordTemplateMapper; private MeetingRecordTemplateMapper meetingRecordTemplateMapper;
private Map<String,String> tidWidRelations; private Map<String,String> tidWidRelations;
public String aesKey;
// 实际处理逻辑 // 实际处理逻辑
public void process() { public void process() {
String key = "meet_process" + meetingId + "_" + (subMeetingId == null ? "" : "subMeetingId"); String key = "meet_process" + meetingId + "_" + (subMeetingId == null ? "" : subMeetingId);
if (!redisUtils.setnx(key, 1, 120)) { if (!redisUtils.setnx(key, 1, 120)) {
log.warn("key already exists in redis!, key: {}", key); log.warn("key already exists in redis!, key: {}", key);
return; return;
} }
Boolean isSuccess = Boolean.FALSE; log.info("线程开始------------>");
long l = System.currentTimeMillis();
Boolean isSuccess = false;
AtomicInteger retryCount = new AtomicInteger(0); AtomicInteger retryCount = new AtomicInteger(0);
MeetingInfo meetingInfo = meetingInfoMapper.selectOne(new LambdaQueryWrapper<MeetingInfo>() MeetingInfo meetingInfo = meetingInfoMapper.selectOne(new LambdaQueryWrapper<MeetingInfo>()
.eq(MeetingInfo::getMeetingId,meetingId) .eq(MeetingInfo::getMeetingId,meetingId)
.eq(subMeetingId != null, MeetingInfo::getSubMeetingId, subMeetingId)); .eq(subMeetingId != null, MeetingInfo::getSubMeetingId, subMeetingId));
if (meetingInfo.getIsPushed()) {
while (retryCount.intValue() <= MAX_RETRY && !isSuccess) { log.warn("邮件已推送, meetingId: {}", meetingId);
return;
}
while (retryCount.intValue() <= MAX_RETRY && isSuccess != null && !isSuccess) {
String hostUid = meetingInfo.getHostUid(); String hostUid = meetingInfo.getHostUid();
if(!tidWidRelations.containsKey(hostUid)){ if(!tidWidRelations.containsKey(hostUid)){
log.error("邮件推送重试失败: 主持人对应关系未配置。meetingId {}", meetingId); log.error("邮件推送重试失败: 主持人对应关系未配置。meetingId {}", meetingId);
...@@ -75,8 +78,10 @@ public class EmailPushTask { ...@@ -75,8 +78,10 @@ public class EmailPushTask {
try { try {
String meetingName; String meetingName;
String xml; String xml;
try(InputStream is = minioUtils.getFile(meetingInfo.getRecordXml())){
xml = convertInputStreamToString(is); try(InputStream inputStream = minioUtils.getFile(meetingInfo.getRecordXml());){
// 解密
xml = AESUtils.decrypt(IoUtil.read(inputStream, StandardCharsets.UTF_8), aesKey);
}catch (Exception e){ }catch (Exception e){
log.error(e.getMessage()); log.error(e.getMessage());
throw new RuntimeException(e); throw new RuntimeException(e);
...@@ -98,7 +103,6 @@ public class EmailPushTask { ...@@ -98,7 +103,6 @@ public class EmailPushTask {
try (InputStream inputStream = minioUtils.getFile(meetingRecordTemplate.getTemplate())) { try (InputStream inputStream = minioUtils.getFile(meetingRecordTemplate.getTemplate())) {
XWPFTemplate template = XWPFTemplate.compile(inputStream).render(dataModel); XWPFTemplate template = XWPFTemplate.compile(inputStream).render(dataModel);
template.writeAndClose(new FileOutputStream(dataNetworkMinutesPath)); template.writeAndClose(new FileOutputStream(dataNetworkMinutesPath));
byte[] recordXmlData = Files.readAllBytes(Paths.get(dataNetworkMinutesPath));
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
...@@ -131,6 +135,8 @@ public class EmailPushTask { ...@@ -131,6 +135,8 @@ public class EmailPushTask {
isSuccess = emailSender.sendEmailWithAttachment(emailPushBuilder); isSuccess = emailSender.sendEmailWithAttachment(emailPushBuilder);
} catch (Exception e) { } catch (Exception e) {
// 异常处理 // 异常处理
e.printStackTrace();
log.error("push email error: {}", e.getMessage());
int currentRetryCount = retryCount.getAndIncrement(); int currentRetryCount = retryCount.getAndIncrement();
if (currentRetryCount > MAX_RETRY) { if (currentRetryCount > MAX_RETRY) {
log.error("达到最大重试次数:meetingId {}", meetingId); log.error("达到最大重试次数:meetingId {}", meetingId);
...@@ -145,15 +151,18 @@ public class EmailPushTask { ...@@ -145,15 +151,18 @@ public class EmailPushTask {
} }
} }
} }
if (isSuccess != null) {
meetingInfoMapper.update(meetingInfo, meetingInfoMapper.update(meetingInfo,
new LambdaUpdateWrapper<MeetingInfo>() new LambdaUpdateWrapper<MeetingInfo>()
.eq(MeetingInfo::getMeetingId,meetingId) .eq(MeetingInfo::getMeetingId,meetingId)
.eq(subMeetingId != null,MeetingInfo::getSubMeetingId,subMeetingId) .eq(subMeetingId != null,MeetingInfo::getSubMeetingId,subMeetingId)
.set(MeetingInfo::getIsPushed,isSuccess) .set(MeetingInfo::getIsPushed,isSuccess)
.set(MeetingInfo::getStatus, isSuccess ? MeetingState.PUSH_SUCCESS.getCode() : MeetingState.PUSH_ERROR.getCode()) .set(MeetingInfo::getStatus, isSuccess ? MeetingState.PUSH_SUCCESS.getCode() : MeetingState.PUSH_ERROR.getCode())
.set(MeetingInfo::getPushRetry,Boolean.TRUE) .set(MeetingInfo::getPushRetry, Boolean.TRUE)
); );
}
redisUtils.del(key); redisUtils.del(key);
log.info("线程结束, 耗时: {} ms", System.currentTimeMillis() - l);
} }
...@@ -195,7 +204,7 @@ public class EmailPushTask { ...@@ -195,7 +204,7 @@ public class EmailPushTask {
public EmailPushTask(String meetingId, String subMeetingId, String savePath, Map<String, Object> metadata, public EmailPushTask(String meetingId, String subMeetingId, String savePath, Map<String, Object> metadata,
MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, RedisUtils redisUtils, EmailSender emailSender, MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, RedisUtils redisUtils, EmailSender emailSender,
MeetingRecordTemplateMapper meetingRecordTemplateMapper, Map<String,String> tidWidRelations) { MeetingRecordTemplateMapper meetingRecordTemplateMapper, Map<String,String> tidWidRelations, String aesKey) {
this.savePath = savePath; this.savePath = savePath;
this.metadata = metadata; this.metadata = metadata;
this.meetingId = meetingId; this.meetingId = meetingId;
...@@ -206,5 +215,6 @@ public class EmailPushTask { ...@@ -206,5 +215,6 @@ public class EmailPushTask {
this.emailSender = emailSender; this.emailSender = emailSender;
this.meetingRecordTemplateMapper = meetingRecordTemplateMapper; this.meetingRecordTemplateMapper = meetingRecordTemplateMapper;
this.tidWidRelations = tidWidRelations; this.tidWidRelations = tidWidRelations;
this.aesKey = aesKey;
} }
} }
\ No newline at end of file
...@@ -117,7 +117,7 @@ public class FileProcessTask { ...@@ -117,7 +117,7 @@ public class FileProcessTask {
// 实际处理逻辑 // 实际处理逻辑
public void process() { public void process() {
boolean isSuccess = false; boolean isSuccess = false;
String key = "meet_process" + meetingId + "_" + (subMeetingId == null ? "" : "subMeetingId"); String key = "meet_process" + meetingId + "_" + (subMeetingId == null ? "" : subMeetingId);
if (!redisUtils.setnx(key, 1, 240)) { if (!redisUtils.setnx(key, 1, 240)) {
log.warn("key already exists in redis!, key: {}", key); log.warn("key already exists in redis!, key: {}", key);
return; return;
...@@ -583,7 +583,7 @@ public class FileProcessTask { ...@@ -583,7 +583,7 @@ public class FileProcessTask {
.set(MeetingInfo::getRecordContent,recordContentPath) .set(MeetingInfo::getRecordContent,recordContentPath)
.set(MeetingInfo::getRecordXml,recordXmlPath) .set(MeetingInfo::getRecordXml,recordXmlPath)
.set(MeetingInfo::getParticipantUsers,meetingInfo.getParticipantUsers()) .set(MeetingInfo::getParticipantUsers,meetingInfo.getParticipantUsers())
.set(MeetingInfo::getIsGenerated,Boolean.TRUE) .set(MeetingInfo::getIsGenerated, success)
.set(MeetingInfo::getTemplateId,meetingRecordTemplate.getId()) .set(MeetingInfo::getTemplateId,meetingRecordTemplate.getId())
.set(MeetingInfo::getTransDocId,meetingInfo.getTransDocId()) .set(MeetingInfo::getTransDocId,meetingInfo.getTransDocId())
.set(MeetingInfo::getSubject,meetingInfo.getSubject()) .set(MeetingInfo::getSubject,meetingInfo.getSubject())
......
...@@ -143,7 +143,8 @@ public class FileProcessProducer { ...@@ -143,7 +143,8 @@ public class FileProcessProducer {
redisUtils, redisUtils,
emailSender, emailSender,
meetingRecordTemplateMapper, meetingRecordTemplateMapper,
tidWidRelations tidWidRelations,
aesKey
); );
// 提交任务到线程池 // 提交任务到线程池
......
...@@ -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;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -21,6 +22,7 @@ public interface MeetingInfoService extends IService<MeetingInfo> { ...@@ -21,6 +22,7 @@ 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);
boolean statisticsEmail(String title, Date startTime, Date endTime, OutputStream outputStream);
/** /**
......
...@@ -9,11 +9,25 @@ import com.cmeeting.pojo.SysUserSyncCategory; ...@@ -9,11 +9,25 @@ import com.cmeeting.pojo.SysUserSyncCategory;
import java.util.List; import java.util.List;
import java.util.List;
public interface SysUserSyncService extends IService<SysUserSync> { public interface SysUserSyncService extends IService<SysUserSync> {
/**
* 根据工号查询部门 limit 1
* @param userId
* @return
*/
String getDeptPathByUserId(String userId); String getDeptPathByUserId(String userId);
/** /**
* 根据工号查询部门集合(部分人在两个部门下)
* @param userId
* @return
*/
List<String> getDeptPathByUserIdAndInSet(String userId);
/**
* 向上获取部门集合,包含当前部门 * 向上获取部门集合,包含当前部门
* *
* @return * @return
......
...@@ -30,6 +30,7 @@ import org.springframework.util.ObjectUtils; ...@@ -30,6 +30,7 @@ import org.springframework.util.ObjectUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -49,13 +50,44 @@ public class SysUserSyncServiceImpl extends ServiceImpl<SysUserSysMapper, SysUse ...@@ -49,13 +50,44 @@ public class SysUserSyncServiceImpl extends ServiceImpl<SysUserSysMapper, SysUse
@Resource @Resource
private ModulePermissionService modulePermissionService; private ModulePermissionService modulePermissionService;
private static Map<String, String> DEPT_MAP = new HashMap<>(12);
static {
DEPT_MAP.put("10340", "集团总部");
DEPT_MAP.put("11683", "中集车辆(集团)股份有限公司");
DEPT_MAP.put("11080", "中集安瑞科投资控股(深圳)有限公司");
DEPT_MAP.put("635364", "中集管理培训(深圳)有限公司");
DEPT_MAP.put("612702", "中集世联达集装箱物流(深圳)有限公司");
DEPT_MAP.put("661082", "柏坚货柜机械维修(深圳)有限公司");
DEPT_MAP.put("745168", "中集世联达国际物流有限公司");
DEPT_MAP.put("766268", "中铁集物流装备有限公司");
DEPT_MAP.put("698027", "深圳中集同创供应链有限公司");
DEPT_MAP.put("674199", "中集模块化建筑投资有限公司");
DEPT_MAP.put("698022", "深圳中集共享后勤服务有限公司");
DEPT_MAP.put("707436", "深圳市集家美寓公寓管理有限公司");
}
@Override @Override
public String getDeptPathByUserId(String userId) { public String getDeptPathByUserId(String userId) {
SysUserSync sysUserSync = baseMapper.selectOne(new LambdaQueryWrapper<SysUserSync>().eq(SysUserSync::getTenantId, perTenantId).eq(SysUserSync::getUserId, userId)); SysUserSync sysUserSync = baseMapper.selectOne(new LambdaQueryWrapper<SysUserSync>()
.eq(SysUserSync::getTenantId, perTenantId).eq(SysUserSync::getUserId, userId)
.select(SysUserSync::getDeptId).last("limit 1"));
String deptId = sysUserSync.getDeptId(); String deptId = sysUserSync.getDeptId();
return getDeptPath("/" + deptId, deptId); return getDeptPath("/" + deptId, deptId);
} }
@Override
public List<String> getDeptPathByUserIdAndInSet(String userId) {
List<SysUserSync> sysUserSyncs = baseMapper.selectList(new LambdaQueryWrapper<SysUserSync>()
.eq(SysUserSync::getTenantId, perTenantId).eq(SysUserSync::getUserId, userId)
.select(SysUserSync::getDeptId));
List<String> collect = sysUserSyncs.stream().map(SysUserSync::getDeptId).collect(Collectors.toList());
List<String> ret = new ArrayList<>();
for (String s : collect) {
ret.add(getDeptPath("/" + s, s));
}
return ret;
}
/** /**
* 向上获取某个部门的路径 * 向上获取某个部门的路径
* *
...@@ -65,7 +97,7 @@ public class SysUserSyncServiceImpl extends ServiceImpl<SysUserSysMapper, SysUse ...@@ -65,7 +97,7 @@ public class SysUserSyncServiceImpl extends ServiceImpl<SysUserSysMapper, SysUse
String parentDeptId = baseMapper.getParentDeptId(deptId, perTenantId); String parentDeptId = baseMapper.getParentDeptId(deptId, perTenantId);
if (StringUtils.isEmpty(parentDeptId)) return deptPath; if (StringUtils.isEmpty(parentDeptId)) return deptPath;
return "/" + parentDeptId + deptPath; return getDeptPath("/" + parentDeptId + deptPath, parentDeptId);
} }
......
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
...@@ -165,4 +165,11 @@ jasypt: ...@@ -165,4 +165,11 @@ jasypt:
# 默认模板 # 默认模板
record-template-path-default: /2025-07-21/a12465sdfsa2gas.docx record-template-path-default: /2025-07-21/a12465sdfsa2gas.docx
removeMenus:
isDev: true isDev: true
statistics:
email-push:
toEmails:
- user:
email: hongdongbao@chatbot.cn
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论