提交 8f1afb93 作者: 洪东保

定时任务修改

父级 4e053985
...@@ -110,6 +110,9 @@ public class CmeetingJob { ...@@ -110,6 +110,9 @@ public class CmeetingJob {
log.info("-------关联企微腾会人员定时任务结束--------"); log.info("-------关联企微腾会人员定时任务结束--------");
} }
/**
* 拉取会议并走一遍总流程(生成纪要->推送邮件)
*/
@Scheduled(fixedRate = 20 * 60 * 1000, initialDelay = 2 * 60 * 1000) @Scheduled(fixedRate = 20 * 60 * 1000, initialDelay = 2 * 60 * 1000)
public void execute() { public void execute() {
if (isDev) { if (isDev) {
...@@ -162,6 +165,7 @@ public class CmeetingJob { ...@@ -162,6 +165,7 @@ public class CmeetingJob {
List<MeetingInfo> meetingInfoList = List<MeetingInfo> meetingInfoList =
meetingInfoService.list(new LambdaQueryWrapper<MeetingInfo>() meetingInfoService.list(new LambdaQueryWrapper<MeetingInfo>()
.eq(MeetingInfo::getIsGenerated, Boolean.FALSE) .eq(MeetingInfo::getIsGenerated, Boolean.FALSE)
.eq(MeetingInfo::getEmailGenerateAccess, true)
.eq(MeetingInfo::getGenerateRetry, Boolean.FALSE) .eq(MeetingInfo::getGenerateRetry, Boolean.FALSE)
.le(MeetingInfo::getSyncTime, LocalDateTime.now().minusHours(1)) .le(MeetingInfo::getSyncTime, LocalDateTime.now().minusHours(1))
); );
......
...@@ -10,6 +10,7 @@ import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper; ...@@ -10,6 +10,7 @@ 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.MinioUtils; import com.cmeeting.util.MinioUtils;
import com.cmeeting.util.RedisUtils;
import com.cmeeting.vo.EmailPush; import com.cmeeting.vo.EmailPush;
import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.XWPFTemplate;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
...@@ -46,12 +47,17 @@ public class EmailPushTask { ...@@ -46,12 +47,17 @@ public class EmailPushTask {
private MeetingInfoMapper meetingInfoMapper; private MeetingInfoMapper meetingInfoMapper;
private MinioUtils minioUtils; private MinioUtils minioUtils;
private RedisUtils redisUtils;
private EmailSender emailSender; private EmailSender emailSender;
private MeetingRecordTemplateMapper meetingRecordTemplateMapper; private MeetingRecordTemplateMapper meetingRecordTemplateMapper;
private Map<String,String> tidWidRelations; private Map<String,String> tidWidRelations;
// 实际处理逻辑 // 实际处理逻辑
public void process() { public void process() {
boolean getKey = redisUtils.setnx("meeting_" + meetingId + subMeetingId, meetingId, 19*60);
if (!getKey) {
return;
}
Boolean isSuccess = Boolean.FALSE; Boolean isSuccess = Boolean.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>()
...@@ -144,7 +150,7 @@ public class EmailPushTask { ...@@ -144,7 +150,7 @@ public class EmailPushTask {
.set(MeetingInfo::getIsPushed,isSuccess) .set(MeetingInfo::getIsPushed,isSuccess)
.set(MeetingInfo::getPushRetry,Boolean.TRUE) .set(MeetingInfo::getPushRetry,Boolean.TRUE)
); );
redisUtils.del("meeting_" + meetingId + subMeetingId);
} }
......
...@@ -9,6 +9,7 @@ import cn.chatbot.openai.completion.chat.ChatMessage; ...@@ -9,6 +9,7 @@ import cn.chatbot.openai.completion.chat.ChatMessage;
import cn.chatbot.openai.completion.chat.ChatMessageRole; import cn.chatbot.openai.completion.chat.ChatMessageRole;
import cn.chatbot.openai.completion.chat.Message; import cn.chatbot.openai.completion.chat.Message;
import cn.chatbot.openai.service.LLMService; import cn.chatbot.openai.service.LLMService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
...@@ -23,14 +24,19 @@ import com.cmeeting.constant.KnowledgePlatformRouteConstant; ...@@ -23,14 +24,19 @@ import com.cmeeting.constant.KnowledgePlatformRouteConstant;
import com.cmeeting.constant.RecordTemplateConstant; import com.cmeeting.constant.RecordTemplateConstant;
import com.cmeeting.constant.UserAdminRouteConstant; import com.cmeeting.constant.UserAdminRouteConstant;
import com.cmeeting.dto.DocResultDto; import com.cmeeting.dto.DocResultDto;
import com.cmeeting.dto.MeetTypeDto;
import com.cmeeting.dto.UserDTO; import com.cmeeting.dto.UserDTO;
import com.cmeeting.email.EmailSender; import com.cmeeting.email.EmailSender;
import com.cmeeting.exception.RobotBaseException; 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;
import com.cmeeting.mapper.primary.UserIdMapper;
import com.cmeeting.pojo.MeetType;
import com.cmeeting.pojo.MeetingInfo; import com.cmeeting.pojo.MeetingInfo;
import com.cmeeting.pojo.MeetingRecordTemplate; import com.cmeeting.pojo.MeetingRecordTemplate;
import com.cmeeting.service.MeetTypeService;
import com.cmeeting.service.MeetingRecordTemplateService;
import com.cmeeting.util.*; import com.cmeeting.util.*;
import com.cmeeting.vo.EmailPush; import com.cmeeting.vo.EmailPush;
import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.XWPFTemplate;
...@@ -92,6 +98,9 @@ public class FileProcessTask { ...@@ -92,6 +98,9 @@ public class FileProcessTask {
private Boolean finalRetry; //表示是兜底重试机制 private Boolean finalRetry; //表示是兜底重试机制
private MeetingInfoMapper meetingInfoMapper; private MeetingInfoMapper meetingInfoMapper;
private MeetingRecordTemplateService meetingRecordTemplateService;
private MeetTypeService meetTypeService;
private UserIdMapper userIdMapper;
private MinioUtils minioUtils; private MinioUtils minioUtils;
private RedisUtils redisUtils; private RedisUtils redisUtils;
private EmailSender emailSender; private EmailSender emailSender;
...@@ -110,11 +119,11 @@ public class FileProcessTask { ...@@ -110,11 +119,11 @@ public class FileProcessTask {
// 实际处理逻辑 // 实际处理逻辑
public void process() { public void process() {
// TODO 根据meeting和subMeetingId上锁 // 根据meeting和subMeetingId上锁
// boolean getKey = redisUtils.setnx("meeting_" + meetingId + subMeetingId, meetingId, 200000); boolean getKey = redisUtils.setnx("meeting_" + meetingId + subMeetingId, meetingId, 19*60);
// while (getKey) { if (!getKey) {
// Thread.sleep(1000); return;
// } }
boolean isSuccess = false; boolean isSuccess = false;
while (retryCount <= MAX_RETRY && !isSuccess) { while (retryCount <= MAX_RETRY && !isSuccess) {
try { try {
...@@ -208,14 +217,12 @@ public class FileProcessTask { ...@@ -208,14 +217,12 @@ public class FileProcessTask {
processLogService.log(meetingId, subMeetingId, "获取的转录文本为空,跳过纪要生成"); processLogService.log(meetingId, subMeetingId, "获取的转录文本为空,跳过纪要生成");
throw new RuntimeException("获取的转录文本为空,跳过纪要生成"); throw new RuntimeException("获取的转录文本为空,跳过纪要生成");
} }
// 3. 处理文件 (调用Claude API等) // 1. 根据转录文件内容recordTextBuffer判断使用模板类型
Long choiceTemplateType = choiceTemplateType(meetingInfo.getSubject());
// TODO 1. 根据转录文件内容recordTextBuffer判断使用模板类型
String choiceTemplateType = choiceTemplateType(meetingInfo.getSubject(), recordTextBuffer.toString());
log.info("choiceTemplateType->{}", choiceTemplateType); log.info("choiceTemplateType->{}", choiceTemplateType);
// TODO 2. 获取这个会议需要使用的一个模板 // 2. 获取这个会议需要使用的一个模板
// 2.1 封装一个方法:入参(a.工号/腾讯会议uid,b.choiceTemplateType);结果(一个模板MeetingRecordTemplate) MeetingRecordTemplate template = meetingRecordTemplateService.getEnabledRecordTemplate(choiceTemplateType, userIdMapper.getWidByTid(meetingInfo.getHostUid()));
MeetingRecordTemplate template = new MeetingRecordTemplate();
List<EmailPush.Attachment> attachments = new ArrayList<>(); List<EmailPush.Attachment> attachments = new ArrayList<>();
String hostUid = meetingInfo.getHostUid(); String hostUid = meetingInfo.getHostUid();
String toUserCode = tidWidRelations.get(meetingInfo.getHostUid()); String toUserCode = tidWidRelations.get(meetingInfo.getHostUid());
...@@ -238,7 +245,6 @@ public class FileProcessTask { ...@@ -238,7 +245,6 @@ public class FileProcessTask {
} }
if (CollectionUtils.isEmpty(attachments)) { if (CollectionUtils.isEmpty(attachments)) {
log.info("用户{}暂无任何模板权限,纪要生成失败", hostUid); log.info("用户{}暂无任何模板权限,纪要生成失败", hostUid);
isSuccess = false;
continue; continue;
} }
if (!tidWidRelations.containsKey(meetingInfo.getHostUid())) { if (!tidWidRelations.containsKey(meetingInfo.getHostUid())) {
...@@ -288,7 +294,7 @@ public class FileProcessTask { ...@@ -288,7 +294,7 @@ public class FileProcessTask {
} }
} }
} }
redisUtils.del("meeting_" + meetingId + subMeetingId);
} }
private byte[] downloadFile(String url) { private byte[] downloadFile(String url) {
...@@ -331,60 +337,70 @@ public class FileProcessTask { ...@@ -331,60 +337,70 @@ public class FileProcessTask {
* 提供会议转录文件和会议主题,判断会议类型 * 提供会议转录文件和会议主题,判断会议类型
* *
* @param subject 会议主题 * @param subject 会议主题
* @param transcript 转录文件内容
* @return * @return
* String token = "AKIAXFAXF62IWJXGLVEE.LnKInaahcMZG9zLsGMH3nTLOw3S3lK5Vcu0+ifnO";
* String apiAddr = llmApiAddr + "/llm/sse-invoke";
* String model = "arn:aws:bedrock:us-east-1:491822380689:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0";
* int maxTokens = 5000;
* // String prompt = "请先对以下会议转写记录进行简要总结(不超过200字),然后根据会议主题以及总结内容判断该会议最可能属于哪种类型:\\n\\n会议主题: {0}\\n会议转写记录: {1}\\n\\n第一步:请简要总结会议的主要内容和目的(不超过200字)。\\n\\n第二步:根据上述总结和会议主题,将会议分类为以下类型之一:\\n1. 项目沟通会 - 与具体项目进展、问题讨论相关的会议\\n2. 重要会议 - 高层决策、战略规划等重要会议\\n3. 启动会 - 项目启动、活动筹备等初始会议\\n4. 其他 - 不符合以上任何分类\\n\\n分类权重判断规则:\\n- 基础权重分配:会议内容总结(70%)、会议主题(30%)\\n- 会议主题权重动态调整:\\n * 如果会议主题包含明确分类关键词(如\\\"启动会\\\"、\\\"项目沟通\\\"、\\\"战略决策\\\"等),则会议主题权重提升至60%,总结内容权重调整为40%\\n * 如果会议主题过于简单或模糊(如仅包含\\\"沟通\\\"、\\\"讨论\\\"、\\\"会议\\\"等通用词),则会议主题权重降低至15%,总结内容权重提升至85%\\n- 一致性判断:如果会议主题和总结内容指向不同分类,优先采用内容总结的分类,除非会议主题非常明确且规范\\n\\n输出格式:\\n请只返回分类名称(如\\\"项目沟通会\\\"),不要包含其他内容(如生成的会议总结等)。";
* String prompt = "## 角色定义\n" +
* "你是一位会议分类师,擅长对各种类型会议进行分类。\n" +
* "\n" +
* "请对以下会议转写记录进行全面而精炼的总结(尽量控制在500字以内,字数可以根据会议转写记录长度适当进行调整),然后根据会议主题以及总结内容判断该会议属于的类型:\n" +
* "\n" +
* "会议主题: {subject}\n" +
* "会议转写记录: {transcript}\n" +
* "\n" +
* "识别会议类型步骤如下:\n" +
* "第一步:识别会议名称/标题(如:项目例会,数据问题讨论);如果识别不出来,标注“暂无”;\n" +
* "第二步:根据识别出来的会议名称进行分类(如:数据问题讨论,讨论会)。如果会议名称如:快速会议,张三预定的会议,分类为“其他”。如果是暂无,则进入第三步:\n" +
* "第三步:总结会议的主要内容和目的(尽量控制在500字以内,字数可以根据会议转写记录长度适当进行调整)。确保涵盖所有关键讨论内容、重要决策和行动项,捕捉所有实质性内容。摘要应当完整反映会议的核心目的,不遗漏重要信息。\n" +
* "\n" +
* "第三步:根据上述内容和目的总结,将会议分类为以下类型之一:\n" +
* "1. 项目例会 - 会议有周期标签。要讨论很多件事情,每件事情讨论时间很短。\n" +
* "2. 启动会 - 项目启动、活动筹备等初始会议,各方代表发言。\n" +
* "3. 讨论会 - 只针对一到两个事件针对性讨论,可能是讨论方案。\n" +
* "4. 其他 - 不符合上面任意一类。\n" +
* "\n" +
* "\n" +
* "输出格式:\n" +
* "{{\n" +
* " \"classification\": 类型\n" +
* "}}\n" +
* "\n" +
* "注意:\n" +
* "1.请严格按照输出格式以JSON格式返回数据,所有字段都必须包含。\n" +
* "2.输出必须是严格有效的JSON格式,可以直接被解析。不要带有json标记,不要包含其他内容。";
* //占位符信息替换
* String formatPrompt = formatMessage(prompt, subject, transcript);
* List<Message> messages = new ArrayList<>();
* ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), formatPrompt);
* messages.add(chatMessage);
*
* // 调用Claude API处理文件
* String response = call_llm(apiAddr, model, token, messages, maxTokens);
* JSONObject object = JSONObject.parseObject(response);
* String retStr = "通用会议";
* if (object != null) {
* String classification = object.getString("classification");
* if (StrUtil.isNotBlank(classification)) {
* retStr = classification;
* }
* }
*/ */
private String choiceTemplateType(String subject, String transcript) { private Long choiceTemplateType(String subject) {
String token = "AKIAXFAXF62IWJXGLVEE.LnKInaahcMZG9zLsGMH3nTLOw3S3lK5Vcu0+ifnO"; Long type = 1L;
String apiAddr = llmApiAddr + "/llm/sse-invoke"; List<MeetType> meetTypeList = meetTypeService.list(new LambdaQueryWrapper<MeetType>().select(MeetType::getId, MeetType::getName));
String model = "arn:aws:bedrock:us-east-1:491822380689:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0"; if (CollUtil.isNotEmpty(meetTypeList)) {
int maxTokens = 5000; type = meetTypeList.get(0).getId();
// String prompt = "请先对以下会议转写记录进行简要总结(不超过200字),然后根据会议主题以及总结内容判断该会议最可能属于哪种类型:\\n\\n会议主题: {0}\\n会议转写记录: {1}\\n\\n第一步:请简要总结会议的主要内容和目的(不超过200字)。\\n\\n第二步:根据上述总结和会议主题,将会议分类为以下类型之一:\\n1. 项目沟通会 - 与具体项目进展、问题讨论相关的会议\\n2. 重要会议 - 高层决策、战略规划等重要会议\\n3. 启动会 - 项目启动、活动筹备等初始会议\\n4. 其他 - 不符合以上任何分类\\n\\n分类权重判断规则:\\n- 基础权重分配:会议内容总结(70%)、会议主题(30%)\\n- 会议主题权重动态调整:\\n * 如果会议主题包含明确分类关键词(如\\\"启动会\\\"、\\\"项目沟通\\\"、\\\"战略决策\\\"等),则会议主题权重提升至60%,总结内容权重调整为40%\\n * 如果会议主题过于简单或模糊(如仅包含\\\"沟通\\\"、\\\"讨论\\\"、\\\"会议\\\"等通用词),则会议主题权重降低至15%,总结内容权重提升至85%\\n- 一致性判断:如果会议主题和总结内容指向不同分类,优先采用内容总结的分类,除非会议主题非常明确且规范\\n\\n输出格式:\\n请只返回分类名称(如\\\"项目沟通会\\\"),不要包含其他内容(如生成的会议总结等)。"; for (MeetType meetType : meetTypeList) {
String prompt = "## 角色定义\n" + if (subject.contains(meetType.getName())) {
"你是一位会议分类师,擅长对各种类型会议进行分类。\n" + type = meetType.getId();
"\n" + break;
"请对以下会议转写记录进行全面而精炼的总结(尽量控制在500字以内,字数可以根据会议转写记录长度适当进行调整),然后根据会议主题以及总结内容判断该会议属于的类型:\n" + }
"\n" +
"会议主题: {subject}\n" +
"会议转写记录: {transcript}\n" +
"\n" +
"识别会议类型步骤如下:\n" +
"第一步:识别会议名称/标题(如:项目例会,数据问题讨论);如果识别不出来,标注“暂无”;\n" +
"第二步:根据识别出来的会议名称进行分类(如:数据问题讨论,讨论会)。如果会议名称如:快速会议,张三预定的会议,分类为“其他”。如果是暂无,则进入第三步:\n" +
"第三步:总结会议的主要内容和目的(尽量控制在500字以内,字数可以根据会议转写记录长度适当进行调整)。确保涵盖所有关键讨论内容、重要决策和行动项,捕捉所有实质性内容。摘要应当完整反映会议的核心目的,不遗漏重要信息。\n" +
"\n" +
"第三步:根据上述内容和目的总结,将会议分类为以下类型之一:\n" +
"1. 项目例会 - 会议有周期标签。要讨论很多件事情,每件事情讨论时间很短。\n" +
"2. 启动会 - 项目启动、活动筹备等初始会议,各方代表发言。\n" +
"3. 讨论会 - 只针对一到两个事件针对性讨论,可能是讨论方案。\n" +
"4. 其他 - 不符合上面任意一类。\n" +
"\n" +
"\n" +
"输出格式:\n" +
"{{\n" +
" \"classification\": 类型\n" +
"}}\n" +
"\n" +
"注意:\n" +
"1.请严格按照输出格式以JSON格式返回数据,所有字段都必须包含。\n" +
"2.输出必须是严格有效的JSON格式,可以直接被解析。不要带有json标记,不要包含其他内容。";
//占位符信息替换
String formatPrompt = formatMessage(prompt, subject, transcript);
List<Message> messages = new ArrayList<>();
ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), formatPrompt);
messages.add(chatMessage);
// 调用Claude API处理文件
String response = call_llm(apiAddr, model, token, messages, maxTokens);
JSONObject object = JSONObject.parseObject(response);
String retStr = "通用会议";
if (object != null) {
String classification = object.getString("classification");
if (StrUtil.isNotBlank(classification)) {
retStr = classification;
} }
} }
return retStr; return type;
} }
private String formatMessage(String pattern, Object... args) { private String formatMessage(String pattern, Object... args) {
...@@ -459,9 +475,7 @@ public class FileProcessTask { ...@@ -459,9 +475,7 @@ public class FileProcessTask {
"text/plain; charset=utf-8", // MIME类型 "text/plain; charset=utf-8", // MIME类型
recordData // 字节内容 recordData // 字节内容
); );
//将转录文件存到知识向量库 //将转录文件存到知识向量库--用于问答改文档
String url = userAdminConfig.getUserAdminDomain() + "/robotcustom/upload";
Map<String, String> otherParams = new HashMap<>(); Map<String, String> otherParams = new HashMap<>();
otherParams.put("userId", toUserCode); otherParams.put("userId", toUserCode);
otherParams.put("tenantId", permTenantId); otherParams.put("tenantId", permTenantId);
...@@ -683,7 +697,8 @@ public class FileProcessTask { ...@@ -683,7 +697,8 @@ public class FileProcessTask {
public FileProcessTask(List<String> recordFileIdList, String meetingId, String subMeetingId, String savePath, Map<String, Object> metadata, public FileProcessTask(List<String> recordFileIdList, String meetingId, String subMeetingId, String savePath, Map<String, Object> metadata,
MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, RedisUtils redisUtils, EmailSender emailSender, MeetingRecordTemplateMapper meetingRecordTemplateMapper, MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, RedisUtils redisUtils, EmailSender emailSender,
MeetingRecordTemplateMapper meetingRecordTemplateMapper, MeetingRecordTemplateService meetingRecordTemplateService, MeetTypeService meetTypeService, UserIdMapper userIdMapper,
String llmApiAddr, Boolean finalRetry, ProcessLogService processLogService, List<UserDTO.TemplateAuthorizedUserDTO> authorizedUsers, Map<String, String> tidWidRelations, String llmApiAddr, Boolean finalRetry, ProcessLogService processLogService, List<UserDTO.TemplateAuthorizedUserDTO> authorizedUsers, Map<String, String> tidWidRelations,
UserAdminConfig userAdminConfig, String adminToken, String applicationId, String fileDownloadPath, String permTenantId) { UserAdminConfig userAdminConfig, String adminToken, String applicationId, String fileDownloadPath, String permTenantId) {
this.recordFileIdList = recordFileIdList; this.recordFileIdList = recordFileIdList;
...@@ -696,6 +711,9 @@ public class FileProcessTask { ...@@ -696,6 +711,9 @@ public class FileProcessTask {
this.redisUtils = redisUtils; this.redisUtils = redisUtils;
this.emailSender = emailSender; this.emailSender = emailSender;
this.meetingRecordTemplateMapper = meetingRecordTemplateMapper; this.meetingRecordTemplateMapper = meetingRecordTemplateMapper;
this.meetingRecordTemplateService = meetingRecordTemplateService;
this.meetTypeService = meetTypeService;
this.userIdMapper = userIdMapper;
this.llmApiAddr = llmApiAddr; this.llmApiAddr = llmApiAddr;
this.finalRetry = finalRetry; this.finalRetry = finalRetry;
this.processLogService = processLogService; this.processLogService = processLogService;
......
...@@ -87,9 +87,12 @@ public class MeetingInfo implements Serializable { ...@@ -87,9 +87,12 @@ public class MeetingInfo implements Serializable {
*/ */
private Boolean isGenerated; private Boolean isGenerated;
/** /**
* 推送邮件许可 为false不推送 * 生成纪要许可
*/ */
private Boolean emailGenerateAccess; private Boolean emailGenerateAccess;
/**
* 推送邮件许可 为false不推送
*/
private Boolean emailPushAccess; private Boolean emailPushAccess;
/** /**
* 是否推送邮件完成 * 是否推送邮件完成
......
...@@ -7,6 +7,7 @@ import com.cmeeting.job.FileProcessTask; ...@@ -7,6 +7,7 @@ import com.cmeeting.job.FileProcessTask;
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;
import com.cmeeting.mapper.primary.UserIdMapper;
import com.cmeeting.pojo.UserId; import com.cmeeting.pojo.UserId;
import com.cmeeting.util.MinioUtils; import com.cmeeting.util.MinioUtils;
import com.cmeeting.util.RedisUtils; import com.cmeeting.util.RedisUtils;
...@@ -49,6 +50,12 @@ public class FileProcessProducer { ...@@ -49,6 +50,12 @@ public class FileProcessProducer {
@Resource @Resource
private MeetingRecordTemplateMapper meetingRecordTemplateMapper; private MeetingRecordTemplateMapper meetingRecordTemplateMapper;
@Resource @Resource
private MeetingRecordTemplateService meetingRecordTemplateService;
@Resource
private MeetTypeService meetTypeService;
@Resource
private UserIdMapper userIdMapper;
@Resource
private MinioUtils minioUtils; private MinioUtils minioUtils;
@Resource @Resource
private RedisUtils redisUtils; private RedisUtils redisUtils;
...@@ -87,6 +94,9 @@ public class FileProcessProducer { ...@@ -87,6 +94,9 @@ public class FileProcessProducer {
redisUtils, redisUtils,
emailSender, emailSender,
meetingRecordTemplateMapper, meetingRecordTemplateMapper,
meetingRecordTemplateService,
meetTypeService,
userIdMapper,
llmApiAddr, llmApiAddr,
finalRetry, finalRetry,
processLogService, processLogService,
......
...@@ -32,6 +32,7 @@ public interface ModulePermissionService extends IService<ModulePermission> { ...@@ -32,6 +32,7 @@ public interface ModulePermissionService extends IService<ModulePermission> {
*/ */
List<ModulePermission> checkPermission(List<String> deptIds, String userId); List<ModulePermission> checkPermission(List<String> deptIds, String userId);
List<Long> checkPermission(List<String> deptIds, String userId, Integer purpose); List<Long> checkPermission(List<String> deptIds, String userId, Integer purpose);
Boolean checkAdminPermission(List<String> deptIds, String userId);
Boolean checkPermission(List<String> deptIds, String userId, Integer purpose, Long targetId); Boolean checkPermission(List<String> deptIds, String userId, Integer purpose, Long targetId);
Boolean personalStatus(String userId); Boolean personalStatus(String userId);
......
...@@ -204,7 +204,7 @@ public class ModulePermissionServiceImpl extends ServiceImpl<ModulePermissionMap ...@@ -204,7 +204,7 @@ public class ModulePermissionServiceImpl extends ServiceImpl<ModulePermissionMap
@Override @Override
public List<ModulePermission> checkPermission(List<String> deptIds, String userId) { public List<ModulePermission> checkPermission(List<String> deptIds, String userId) {
return this.list(new LambdaQueryWrapper<ModulePermission>() return this.list(new LambdaQueryWrapper<ModulePermission>()
.and(e -> e.eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_DEPT).in(ModulePermission::getRelId, deptIds) .and(e -> e.eq(CollUtil.isNotEmpty(deptIds), ModulePermission::getType, RecordTemplateConstant.REL_TYPE_DEPT).in(ModulePermission::getRelId, deptIds)
.or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, userId)) .or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, userId))
.select(ModulePermission::getTargetId) .select(ModulePermission::getTargetId)
); );
...@@ -214,7 +214,7 @@ public class ModulePermissionServiceImpl extends ServiceImpl<ModulePermissionMap ...@@ -214,7 +214,7 @@ public class ModulePermissionServiceImpl extends ServiceImpl<ModulePermissionMap
public List<Long> checkPermission(List<String> deptIds, String userId, Integer purpose) { public List<Long> checkPermission(List<String> deptIds, String userId, Integer purpose) {
List<ModulePermission> list = this.list(new LambdaQueryWrapper<ModulePermission>() List<ModulePermission> list = this.list(new LambdaQueryWrapper<ModulePermission>()
.eq(ModulePermission::getPurpose, purpose) .eq(ModulePermission::getPurpose, purpose)
.and(e -> e.eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_DEPT).in(ModulePermission::getRelId, deptIds) .and(e -> e.eq(CollUtil.isNotEmpty(deptIds), ModulePermission::getType, RecordTemplateConstant.REL_TYPE_DEPT).in(ModulePermission::getRelId, deptIds)
.or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, userId) .or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, userId)
.or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, CategoryConstant.ALL_EN) .or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, CategoryConstant.ALL_EN)
).select(ModulePermission::getTargetId) ).select(ModulePermission::getTargetId)
...@@ -223,6 +223,18 @@ public class ModulePermissionServiceImpl extends ServiceImpl<ModulePermissionMap ...@@ -223,6 +223,18 @@ public class ModulePermissionServiceImpl extends ServiceImpl<ModulePermissionMap
} }
@Override @Override
public Boolean checkAdminPermission(List<String> deptIds, String userId) {
List<ModulePermission> list = this.list(new LambdaQueryWrapper<ModulePermission>()
.eq(ModulePermission::getPurpose, PermissionPruposeType.ADMIN_AUTH)
.and(e -> e.eq(CollUtil.isNotEmpty(deptIds), ModulePermission::getType, RecordTemplateConstant.REL_TYPE_DEPT).in(ModulePermission::getRelId, deptIds)
.or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, userId)
.or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, CategoryConstant.ALL_EN)
).select(ModulePermission::getId)
);
return CollUtil.isNotEmpty(list);
}
@Override
public Boolean checkPermission(List<String> deptIds, String userId, Integer purpose, Long targetId) { public Boolean checkPermission(List<String> deptIds, String userId, Integer purpose, Long targetId) {
boolean flag = purpose.equals(PermissionPruposeType.TEMPLATE_TYPE_PERMISSION) || purpose.equals(PermissionPruposeType.TEMPLATE_PERMISSION); boolean flag = purpose.equals(PermissionPruposeType.TEMPLATE_TYPE_PERMISSION) || purpose.equals(PermissionPruposeType.TEMPLATE_PERMISSION);
if (flag && targetId != null) { if (flag && targetId != null) {
......
package com.cmeeting.service.impl; package com.cmeeting.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.constant.PermissionPruposeType;
import com.cmeeting.dto.UserDTO; import com.cmeeting.dto.UserDTO;
import com.cmeeting.log.service.ProcessLogService; import com.cmeeting.log.service.ProcessLogService;
import com.cmeeting.mapper.primary.AuthMapper; import com.cmeeting.mapper.primary.AuthMapper;
import com.cmeeting.mapper.primary.MeetingInfoMapper; import com.cmeeting.mapper.primary.MeetingInfoMapper;
import com.cmeeting.mapper.primary.TecentMeetingMapper; import com.cmeeting.mapper.primary.TecentMeetingMapper;
import com.cmeeting.mapper.secondary.SysUserSysMapper; import com.cmeeting.mapper.secondary.SysUserSysMapper;
import com.cmeeting.pojo.CoreModulePermissions; import com.cmeeting.pojo.*;
import com.cmeeting.pojo.MeetingInfo; import com.cmeeting.service.ModulePermissionService;
import com.cmeeting.pojo.TencentMeetingUser; import com.cmeeting.service.SysUserSyncService;
import com.cmeeting.pojo.WeComUser;
import com.cmeeting.service.TencentMeetingService; import com.cmeeting.service.TencentMeetingService;
import com.cmeeting.util.RedisUtils; import com.cmeeting.util.RedisUtils;
import com.cmeeting.util.SignatureUtil; import com.cmeeting.util.SignatureUtil;
...@@ -64,6 +66,10 @@ public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper, ...@@ -64,6 +66,10 @@ public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,
private RedisUtils redisUtils; private RedisUtils redisUtils;
@Resource @Resource
private ProcessLogService processLogService; private ProcessLogService processLogService;
@Resource
private ModulePermissionService modulePermissionService;
@Resource
private SysUserSyncService sysUserSyncService;
private static final String HMAC_ALGORITHM = "HmacSHA256"; private static final String HMAC_ALGORITHM = "HmacSHA256";
private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
...@@ -134,6 +140,8 @@ public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper, ...@@ -134,6 +140,8 @@ public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,
List<TencentMeetingVO.SimpleMeetingInfo> meetingIds = meetingInfoMapper.getAllMeetingIds(); List<TencentMeetingVO.SimpleMeetingInfo> meetingIds = meetingInfoMapper.getAllMeetingIds();
List<TencentMeetingUser> meetingUsers = tecentMeetingMapper.getAlluser(); List<TencentMeetingUser> meetingUsers = tecentMeetingMapper.getAlluser();
Map<String, String> meetingMap = meetingUsers.stream().collect(Collectors.toMap(TencentMeetingUser::getUserId, TencentMeetingUser::getUserName)); Map<String, String> meetingMap = meetingUsers.stream().collect(Collectors.toMap(TencentMeetingUser::getUserId, TencentMeetingUser::getUserName));
while (currentPage.intValue() <= totalPage) { while (currentPage.intValue() <= totalPage) {
CorpRecordsVO data = fetchMeetingRecords(tencentAdminUserId, 1, startTime, endTime, currentPage.getAndIncrement(), 20); CorpRecordsVO data = fetchMeetingRecords(tencentAdminUserId, 1, startTime, endTime, currentPage.getAndIncrement(), 20);
//设置总页数 //设置总页数
...@@ -225,20 +233,31 @@ public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper, ...@@ -225,20 +233,31 @@ public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,
//判断是否有权限生成纪要 //判断是否有权限生成纪要
boolean generateAccess; boolean generateAccess;
boolean emailPushAccess; boolean emailPushAccess;
UserDTO userDTO = accessUserIds.stream().filter(item -> item.getTid().equals(hostId)).findFirst().get();
String userId = weComUserMap.get(userDTO.getWid()).getUserId();
// 1. 智能体需要授权 // 1. 智能体需要授权
generateAccess = accessUserIds.stream().anyMatch(item -> item.getTid().equals(hostId)); generateAccess = accessUserIds.stream().anyMatch(item -> item.getTid().equals(hostId));
log.info("智能体是否授权: {}", generateAccess); log.info("用户: {}, 智能体是否授权: {}", userId, generateAccess);
UserDTO userDTO = accessUserIds.stream().filter(item -> item.getTid().equals(hostId)).findFirst().get();
String email = userDTO.getEmail(); String email = userDTO.getEmail();
// TODO 要改
// 2. 腾讯会议和企业微信信息同步过并且绑定关系 // 2. 腾讯会议和企业微信信息同步过并且绑定关系
// 3. 用户在超管授权了的人员里面
// 3. 用户自己没有关闭会议纪要功能 // 3. 用户自己没有关闭会议纪要功能
// 满足以上所有则emailGenerateAccess为ture // 满足以上所有则emailGenerateAccess为ture
generateAccess = weComUserMap.containsKey(userDTO.getWid()) ? weComUserMap.get(userDTO.getWid()).getEmailPushAccess() : Boolean.FALSE; generateAccess = generateAccess && weComUserMap.containsKey(userDTO.getWid());
log.info("uid是否绑定企业微信: {}", generateAccess);
List<SysUserSyncCategory> categoryList = sysUserSyncService.getCategoryListByUserId(userId);
List<String> deptIds = categoryList.stream().map(SysUserSyncCategory::getDeptId).collect(Collectors.toList());
generateAccess = generateAccess && modulePermissionService.checkAdminPermission(deptIds, userId);
log.info("超管是否授权给用户: {}", generateAccess);
generateAccess = generateAccess && modulePermissionService.personalStatus(userId);
log.info("个人是否开启纪要功能: {}", generateAccess);
// 是否推送邮箱 // 是否推送邮箱
emailPushAccess = weComUserMap.containsKey(userDTO.getWid()) ? weComUserMap.get(userDTO.getWid()).getEmailPushAccess() : Boolean.FALSE; emailPushAccess = generateAccess && (weComUserMap.containsKey(userDTO.getWid()) ? weComUserMap.get(userDTO.getWid()).getEmailPushAccess() : Boolean.FALSE);
log.info("推送邮箱: {}", emailPushAccess); log.info("是否推送邮箱: {}", emailPushAccess);
// 查询会议开始和结束时间 // 查询会议开始和结束时间
MeetingInfo startAndEndTimeByMeetingId = TencentMeetingApiUtil.getStartAndEndTimeByMeetingId(meetingId); MeetingInfo startAndEndTimeByMeetingId = TencentMeetingApiUtil.getStartAndEndTimeByMeetingId(meetingId);
//会议基本信息保存 //会议基本信息保存
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论