提交 145b1b92 作者: 张开石

1、生成会议纪要定时任务:转录文本和会议纪要加密保存到文件服务器

2、导出转写原文接口:添加文件解密逻辑
父级 b0bf952a
...@@ -12,6 +12,7 @@ import com.cmeeting.mapper.primary.UserIdMapper; ...@@ -12,6 +12,7 @@ import com.cmeeting.mapper.primary.UserIdMapper;
import com.cmeeting.pojo.MeetingInfo; import com.cmeeting.pojo.MeetingInfo;
import com.cmeeting.pojo.MeetingRecordTemplate; import com.cmeeting.pojo.MeetingRecordTemplate;
import com.cmeeting.service.MeetingInfoService; import com.cmeeting.service.MeetingInfoService;
import com.cmeeting.util.AESUtils;
import com.cmeeting.util.MinioUtils; import com.cmeeting.util.MinioUtils;
import com.cmeeting.util.R; import com.cmeeting.util.R;
import com.cmeeting.vo.EmailPush; import com.cmeeting.vo.EmailPush;
...@@ -36,10 +37,7 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -36,10 +37,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream; import java.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
...@@ -65,6 +63,8 @@ public class MeetingInfoController { ...@@ -65,6 +63,8 @@ public class MeetingInfoController {
private String permissionApplicationId; private String permissionApplicationId;
@Value(value = "${userAdmin.file-download-path}") @Value(value = "${userAdmin.file-download-path}")
private String fileDownloadPath; private String fileDownloadPath;
@Value("${aec.key}")
public String aesKey;
@PostMapping("/updateRecordXml") @PostMapping("/updateRecordXml")
public R updateRecordXml(@RequestBody MeetingInfoVO vo) { public R updateRecordXml(@RequestBody MeetingInfoVO vo) {
...@@ -132,7 +132,9 @@ public class MeetingInfoController { ...@@ -132,7 +132,9 @@ public class MeetingInfoController {
public void exportMeetingRecord(@RequestBody MeetingInfoVO vo, HttpServletResponse response){ public void exportMeetingRecord(@RequestBody MeetingInfoVO vo, HttpServletResponse response){
try { try {
MeetingInfo meetingInfo = meetingInfoService.getById(vo.getId()); MeetingInfo meetingInfo = meetingInfoService.getById(vo.getId());
String content = minioUtils.getFileText(meetingInfo.getRecordContent()); InputStream inputStream = minioUtils.getFile(meetingInfo.getRecordContent());
// 解密
String content = AESUtils.decrypt(IoUtil.read(inputStream, StandardCharsets.UTF_8), aesKey);
String fileName = String.format(meetingInfo.getSubject() + "_转写原文_%s.docx", DateUtil.today()); String fileName = String.format(meetingInfo.getSubject() + "_转写原文_%s.docx", DateUtil.today());
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
......
package com.cmeeting.job; package com.cmeeting.job;
import cn.chatbot.meeting.DebugOutputTool;
import cn.chatbot.meeting.LLMConfig; import cn.chatbot.meeting.LLMConfig;
import cn.chatbot.meeting.LLMResult; import cn.chatbot.meeting.LLMResult;
import cn.chatbot.meeting.MeetingProcess; import cn.chatbot.meeting.MeetingProcess;
...@@ -12,17 +11,10 @@ import cn.chatbot.openai.service.LLMService; ...@@ -12,17 +11,10 @@ import cn.chatbot.openai.service.LLMService;
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;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
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.ad.util.SecurityUtil;
import com.cmeeting.constant.KnowledgePlatformRouteConstant;
import com.cmeeting.constant.MeetingState; import com.cmeeting.constant.MeetingState;
import com.cmeeting.constant.RecordTemplateConstant; import com.cmeeting.constant.RecordTemplateConstant;
import com.cmeeting.constant.UserAdminRouteConstant;
import com.cmeeting.dto.DocResultDto;
import com.cmeeting.dto.UserDTO; import com.cmeeting.dto.UserDTO;
import com.cmeeting.email.EmailSender; import com.cmeeting.email.EmailSender;
import com.cmeeting.log.service.ProcessLogService; import com.cmeeting.log.service.ProcessLogService;
...@@ -54,20 +46,15 @@ import org.apache.commons.io.IOUtils; ...@@ -54,20 +46,15 @@ import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor; import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*; import java.io.*;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.time.*;
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;
...@@ -111,6 +98,8 @@ public class FileProcessTask { ...@@ -111,6 +98,8 @@ public class FileProcessTask {
private String applicationId; private String applicationId;
private String fileDownloadPath; private String fileDownloadPath;
private String permTenantId; private String permTenantId;
// AES加密秘钥
private String aesKey;
// 实际处理逻辑 // 实际处理逻辑
...@@ -308,7 +297,7 @@ public class FileProcessTask { ...@@ -308,7 +297,7 @@ public class FileProcessTask {
processedResult = processWithClaude(recordTextBuffer.toString(),meetingDate,participantNames,template.getPrompt()); processedResult = processWithClaude(recordTextBuffer.toString(),meetingDate,participantNames,template.getPrompt());
} }
String minutesPath = saveResult(processedResult, recordTextBuffer.toString().getBytes(StandardCharsets.UTF_8), meetingInfo,toUserCode, template); String minutesPath = saveResult(processedResult, recordTextBuffer.toString(), meetingInfo,toUserCode, template);
try(InputStream is = new FileInputStream(minutesPath)){ try(InputStream is = new FileInputStream(minutesPath)){
byte[] meetingMinutesBytes = IOUtils.toByteArray(is); byte[] meetingMinutesBytes = IOUtils.toByteArray(is);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyyMMdd"); DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyyMMdd");
...@@ -487,13 +476,15 @@ public class FileProcessTask { ...@@ -487,13 +476,15 @@ public class FileProcessTask {
* @param toUserCode 人员工号 * @param toUserCode 人员工号
* @param meetingRecordTemplate 模板信息 * @param meetingRecordTemplate 模板信息
*/ */
private String saveResult(String content, byte[] recordData, MeetingInfo meetingInfo,String toUserCode,MeetingRecordTemplate meetingRecordTemplate) { private String saveResult(String content, String recordData, MeetingInfo meetingInfo, String toUserCode, MeetingRecordTemplate meetingRecordTemplate) {
String meetingName; String meetingName;
//转录文件临时存储路径 String uuid = IdUtil.fastSimpleUUID();
// String recordContentPath = meetingId + "-recordContent-" + IdUtil.fastSimpleUUID() + ".txt"; String today = DateUtil.today();
String recordContentPath = null;
//生成的xml临时存储路径 // 生成的xml临时存储路径
String recordXmlPath = meetingId + "-recordXmlPath-" + IdUtil.fastSimpleUUID() + ".xml"; String recordXmlPath = String.format("%s/%s", today, meetingId + "-recordXmlPath-" + uuid + ".xml");
// 腾讯会议转录文件存储路径
String recordContentPath = String.format("%s/%s", today, meetingId + "-recordContent-" + uuid + ".txt") ;
//填充后的会议纪要名称 //填充后的会议纪要名称
String meetingMinutesFileName; String meetingMinutesFileName;
//填充后的会议纪要word文件临时路径 //填充后的会议纪要word文件临时路径
...@@ -501,38 +492,16 @@ public class FileProcessTask { ...@@ -501,38 +492,16 @@ public class FileProcessTask {
boolean success = false; boolean success = false;
try { try {
String subject = meetingInfo.getSubject(); String subject = meetingInfo.getSubject();
String fileName = String.format(subject + "_转写原文_%s.txt", DateUtil.today());
MultipartFile multipartFile = new CustomMultipartFile( // 将转录文件保存到MinIO
"file", // 表单中的字段名 String encryptedRecordData = AESUtils.encrypt(recordData, aesKey);
fileName, // 原始文件名 minioUtils.upload(recordContentPath, encryptedRecordData.getBytes(StandardCharsets.UTF_8));
"text/plain; charset=utf-8", // MIME类型
recordData // 字节内容
);
//将转录文件存到知识向量库
String url = userAdminConfig.getUserAdminDomain() + "/robotcustom/upload";
Map<String, String> otherParams = new HashMap<>();
otherParams.put("userId", toUserCode);
otherParams.put("tenantId", permTenantId);
otherParams.put("layout", "V1");
String responseData = HttpClientKnowledgePlatformUtil.sendPostByFormDataFiles(userAdminConfig.getDocDomain() + KnowledgePlatformRouteConstant.DOC.SIMPLE_DOC_UPLOAD_URL, Arrays.asList(multipartFile), otherParams, null);
if (StringUtils.isNotBlank(responseData)) {
R result = JSON.parseObject(responseData, R.class);
List<DocResultDto> docResultDtoList = JSON.parseObject(JSONObject.toJSONString(result.getData()), new TypeReference<List<DocResultDto>>() {
});
DocResultDto docResultDto = docResultDtoList.get(0);
String previewPath = docResultDto.getPreviewPath();
recordContentPath = previewPath.replaceAll(fileDownloadPath,"");
meetingInfo.setTransDocId(docResultDto.getId());
}else{
processLogService.log(meetingId,subMeetingId,"填充会议纪要失败,上传转录文件到向量知识库失败");
throw new RuntimeException("填充会议纪要失败");
}
//去除内容中除了xml内容以外其他的信息,格式化xml //去除内容中除了xml内容以外其他的信息,格式化xml
String xml = extractXmlFromMarkdown(content); String xml = extractXmlFromMarkdown(content);
// minioUtils.upload(recordContentPath,recordData); String encryptedXml = AESUtils.encrypt(xml, aesKey);
minioUtils.upload(recordXmlPath,xml.getBytes(StandardCharsets.UTF_8)); minioUtils.upload(recordXmlPath,encryptedXml.getBytes(StandardCharsets.UTF_8));
//将xml格式的内容转换为map,用于填充模板 //将xml格式的内容转换为map,用于填充模板
Map<String, Object> dataModel = convertXmlToMap(xml); Map<String, Object> dataModel = convertXmlToMap(xml);
//判断会议名称关键词,如果是用户自己定义的主题,不做修改 //判断会议名称关键词,如果是用户自己定义的主题,不做修改
...@@ -737,7 +706,8 @@ public class FileProcessTask { ...@@ -737,7 +706,8 @@ public class FileProcessTask {
String tencentSdkId, String tencentSecretId, String tencentSecretKey, String tencentAdminUserId, String tencentSdkId, String tencentSecretId, String tencentSecretKey, String tencentAdminUserId,
MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, RedisUtils redisUtils, EmailSender emailSender, MeetingRecordTemplateMapper meetingRecordTemplateMapper, MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, RedisUtils redisUtils, EmailSender emailSender, MeetingRecordTemplateMapper meetingRecordTemplateMapper,
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,
String aesKey) {
this.recordFileIdList = recordFileIdList; this.recordFileIdList = recordFileIdList;
this.savePath = savePath; this.savePath = savePath;
this.metadata = metadata; this.metadata = metadata;
...@@ -763,5 +733,6 @@ public class FileProcessTask { ...@@ -763,5 +733,6 @@ public class FileProcessTask {
this.applicationId = applicationId; this.applicationId = applicationId;
this.fileDownloadPath = fileDownloadPath; this.fileDownloadPath = fileDownloadPath;
this.permTenantId = permTenantId; this.permTenantId = permTenantId;
this.aesKey = aesKey;
} }
} }
\ No newline at end of file
...@@ -33,7 +33,8 @@ public class FileProcessProducer { ...@@ -33,7 +33,8 @@ public class FileProcessProducer {
@Autowired @Autowired
private ThreadPoolTaskExecutor fileProcessExecutor; private ThreadPoolTaskExecutor fileProcessExecutor;
@Value("${aec.key}")
public String aesKey;
@Autowired @Autowired
private FileProcessCallbackHandler callbackHandler; private FileProcessCallbackHandler callbackHandler;
@Value(value = "${tencent.appId}") @Value(value = "${tencent.appId}")
...@@ -110,7 +111,8 @@ public class FileProcessProducer { ...@@ -110,7 +111,8 @@ public class FileProcessProducer {
adminToken, adminToken,
applicationId, applicationId,
fileDownloadPath, fileDownloadPath,
permTenantId permTenantId,
aesKey
); );
// 提交任务到线程池 // 提交任务到线程池
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论